home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992…ugust: Hack to the Future / ADC Developer CD (1992-08) (''Hack To The Future'')_iso / Dev.CD 199208.iso / Technical Documentation / Inside Macintosh / New Inside Mac - draft / Collaborative Computing / Collaborative Computing
Encoding:
Text File  |  1992-01-14  |  3.5 MB  |  9,308 lines  |  [ONLN/HLX2]

Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
  1. Inside Macintosh:
  2. Collaborative Computing
  3.     Apple Computer, Inc. 
  4. © 1991, Apple Computer, Inc.
  5. All rights reserved.
  6. Printed in the United States of 
  7. America.
  8. The Apple logo is a registered trademark of Apple Computer, Inc. Use of the “keyboard” 
  9. Apple logo (Option-Shift-K) for commercial purposes without the prior written consent of 
  10. Apple may constitute trademark infringement and unfair compe-tition in violation of federal and state laws.
  11. Apple Computer, Inc. 
  12. 20525 Mariani Avenue  
  13. Cupertino, CA  95014-6299
  14. 408-996-1010  
  15. Apple, the Apple logo, APDA, AppleLink, AppleShare, 
  16. AppleTalk, Apple IIGS, A/UX, EtherTalk, HyperCard, Hyper-Talk, ImageWriter, LaserWriter, LocalTalk, Mac, Macintosh, MPW, MultiFinder, SANE, and TokenTalk are registered trade-marks of Apple Computer, Inc.
  17. Apple Desktop Bus, Balloon Help, Finder, KanjiTalk, Moof, QuickDraw, ResEdit, TrueType, and Zhong-Wen Talk are trade-marks of Apple Computer, Inc.
  18. Helvetica and Times are 
  19. registered trademarks of 
  20. Linotype Company.
  21. ITC Zapf Dingbats is a registered trademark of International Typeface Corporation.
  22. MacPaint is a registered trade-mark of Claris Corporation.
  23. NuBus is a trademark of Texas 
  24. Instruments.
  25. PostScript is a registered trade-mark, and Illustrator is a 
  26. trademark, of Adobe Systems 
  27. Incorporated.
  28. Sony is a registered trademark of Sony Corporation.
  29. UNIX is a registered trademark of UNIX System Laboratories, Inc.
  30. Simultaneously published in the United States and Canada.
  31. Limited Warranty on Media and Replacement
  32. Even though Apple has 
  33. reviewed this manual, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS MANUAL, ITS QUALITY, ACCURACY, MERCHANT-ABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. AS A RESULT, THIS 
  34. MANUAL IS SOLD “AS 
  35. IS,” AND YOU, THE PUR-CHASER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND 
  36. ACCURACY.  
  37. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, 
  38. INDIRECT, SPECIAL, 
  39. INCIDENTAL, OR CONSE-QUENTIAL DAMAGES 
  40. RESULTING FROM ANY 
  41. DEFECT OR INACCURACY IN THIS MANUAL, even if advised of the possibility of such damages.  
  42. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL 
  43. OTHERS, ORAL OR 
  44. WRITTEN, EXPRESS OR 
  45. IMPLIED. No Apple dealer, agent, or employee is 
  46. authorized to make any 
  47. modification, extension, or 
  48. addition to this warranty.  
  49. Some states do not allow the exclusion or limitation of 
  50. implied warranties or liability for incidental or consequential damages, so the above 
  51. limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state.
  52. The Edition Manager
  53. About the Edition Manager1-3
  54. Publishers, Subscribers, and Editions1-4
  55. Using The Edition Manager1-12
  56. Receiving Apple Events From the Edition Manager1-12
  57. Creating the Section Record and Alias Record1-15
  58. Saving a Document Containing Sections1-19
  59. Opening and Closing a Document Containing Sections1-22
  60. Reading and Writing a Section1-25
  61. Formats in an Edition1-25
  62. Opening an Edition1-27
  63. Format Marks1-27
  64. Reading and Writing Edition Data1-28
  65. Closing an Edition1-28
  66. Creating a Publisher1-29
  67. Creating the Edition Container1-32
  68. Opening an Edition Container to Write Data1-35
  69. Creating a Subscriber1-37
  70. Opening an Edition Container to Read Data1-41
  71. Choosing Which Edition Format to Read1-41
  72. Using Publisher and Subscriber Options1-43
  73. Publishing a New Edition While Saving or Manually1-47
  74. Subscribing to an Edition Automatically or Manually1-48
  75. Canceling Sections Within Documents1-48
  76. Locating a Publisher Through a Subscriber1-49
  77. Renaming a Document Containing Sections1-50
  78. Displaying Publisher and Subscriber Borders1-50
  79. Text Borders1-54
  80. Spreadsheet Borders1-55
  81. Object-Oriented Graphics Borders1-55
  82. Bitmapped Graphics Borders1-57
  83. Duplicating Publishers and Subscribers1-57
  84. Modifying a Subscriber1-59
  85. Relocating an Edition1-59
  86. Customizing Dialog Boxes1-59
  87. Subscribing To Non-Edition Files1-62
  88. Getting the Current Edition Opener1-63
  89. Setting an Edition Opener1-63
  90. Calling an Edition Opener Procedure1-63
  91. Opening and Closing Editions1-67
  92. Listing Files That Can Be Subscribed To1-67
  93. Reading From and Writing to Files1-67
  94. Calling a Format I/O Procedure1-68
  95. Reference to the Edition Manager1-69
  96. Routines1-70
  97. Initializing the Edition Manager1-70
  98. Creating and Registering a Section1-71
  99. Creating and Deleting an Edition Container1-76
  100. Setting and Locating a Format Mark1-77
  101. Reading in Edition Data1-79
  102. Writing out Edition Data1-81
  103. Closing an Edition After Reading or Writing1-83
  104. Displaying Dialog Boxes1-85
  105. Locating a Publisher and Edition From a Subscriber1-92
  106. Edition Container Formats1-94
  107. Reading and Writing Non-Edition Files1-95
  108. Summary of the Edition Manager1-98
  109. 1The Edition Manager
  110. This chapter describes how you can use the Edition Manager to allow your users to share and automatically update data from numerous documents and applications. 
  111. The Edition Manager is available only in system software version 7.0. It can be used by many different applications located on a single disk or throughout a network of Macintosh<Superscript\>\xa8  computers. To test for the existence of the Edition Manager, use the Gestalt function, described in the Compatibility Guidelines chapter of this volume.
  112. Read the information in this chapter if you want your application’s documents to share and automatically update data, or if you want to share and automatically update data with documents created by other applications that support the Edition Manager.
  113. For example, a user might want to capture sales figures and totals from within a spreadsheet and then include this information in a word-processing document that summarizes sales for a given month. The Edition Manager establishes a connection between these two documents. When a user modifies the spreadsheet, the information in the word-processing document can be automatically updated to contain the latest changes. To accomplish this, both the spreadsheet application and the word-processing application must support the features of the Edition Manager.
  114. To use this chapter, you should be familiar with sending and receiving high-level events, described in the Events Manager chapter of this volume. Your application must also support Apple<Superscript\>\xa8  events to receive Apple events from the Edition Manager. See the Apple Event Manager chapter in this volume for detailed information.
  115. About the Edition Manager
  116. The Edition Manager provides you with the ability to
  117. n    capture data within a document and integrate it into another document
  118. n    modify information in a document and automatically update any document that shares its data
  119. n    share information between applications on the same computer or across a network of Macintosh computers
  120. Building the capabilities of the Edition Manager into your program is similar to building cut-and-paste features into your program. Text, graphics, spreadsheet cells, database reports—any data that you can select, you can make accessible to other applications that support the Edition Manager.
  121. This chapter first defines the main elements of the Edition Manager and then discusses how to save, open, read, and write a document that shares data. In addition, this chapter describes how to
  122. n    make data accessible to other applications
  123. n    integrate data into numerous documents
  124. n    set update options
  125. n    implement borders
  126. n    modify shared data
  127. n    customize dialog boxes
  128. This chapter also describes an advanced feature that allows applications to share data directly from a file.
  129. Publishers, Subscribers, and Editions
  130. A section is a portion of a document that shares its contents with other documents. The Edition Manager supports two types of sections: publishers and subscribers. A publisher is a section within a document that makes its data available to other documents or applications. A subscriber is a section within a document that obtains its data from other documents or applications.
  131. Your application writes a copy of the data in each publisher to a separate file called an edition container. The actual data that is written to the edition container is referred to as the edition. Your application obtains the data for each subscriber by reading data from the edition container. Note that throughout this chapter, the term edition refers to the edition container and the data it contains. 
  132. You publish data when you want to make it available to other documents and applications. When data is published, it is stored in an edition container. You subscribe to data that a publisher makes available by reading an edition from its container. 
  133. Section and edition container are programmatic terms. You should not use them in your application or your documentation. Use publishers, subscribers, and editions. You should also refrain from using other terms such as publication or subscription to describe the dynamic sharing of information provided by the Edition Manager. Use the terms publish and subscribe to describe the Edition Manager features.<36pt\>\x12 <8bat\>u
  134. Each edition has an icon that is visible from the Finder. Figure 1-1 shows the default 
  135. edition icon. 
  136. The default edition icon
  137. The name that the user specifies for the edition is located next to the edition icon. To create customized edition icons, see the Finder Interface chapter in this volume for detailed information. Figure 1-2 illustrates a document containing a single publisher, its corresponding edition, and a subscriber to the edition in another document.
  138. A publisher, an edition, and a subscriber
  139. Note that the publisher and subscriber borders illustrated in Figure 1-2 may appear slightly different from the borders you see on screen. Figure 1-6 shows a screen-captured image of the publisher and subscriber borders that appear on screen.
  140. Data always flows in one direction, from publisher to edition to subscriber. Documents that contain publishers and subscribers do not have to be open at the same time to share data. Whenever the user saves a document that contains a publisher, the edition changes to reflect the current data from the publisher. All subscribers update their contents from the edition. Any number of subscribers can subscribe to a single edition. 
  141. To create a publisher within a document, a user selects an area of the document to share and chooses Create Publisher from the Edit menu (illustrated later in this chapter). Figure 1-3 shows the dialog box that your application should display when the user chooses Create Publisher.
  142. The publisher dialog box
  143. Your application provides a thumbnail sketch of the edition data that the Edition Manager displays in the preview area of the publisher dialog box. Your preview of the edition in this dialog box should provide a visual cue about the type of information that the user has selected to publish. 
  144. A preview area also appears in the subscriber dialog box (see Figure 1-4). Your preview for an edition in this dialog box should provide a visual cue about the type of information the edition contains. For example, it should allow users to distinguish between text information and spreadsheet arrays. 
  145. The publisher dialog box uses the extended interface of the standard file dialog box that accompanies system software version 7.0. The user navigates through the contents of the disk using the mouse or keyboard.
  146. A user can modify a publisher within a document just like any other portion of a document. As a default, each time a user saves a document containing a publisher, your application should automatically write the publisher’s data to the edition. You also need to provide the user with the choice of sending new publisher data to an edition manually (that is, only at the user’s specific request). You should provide these options by using the publisher options dialog box described later in “Using Publisher and Subscriber Options.”
  147. For example, one user may choose to automatically update an edition each time a document is saved. This update mode is useful for a user who creates a publisher within a spreadsheet application that records stock information. Each time the user updates the stock information and saves the spreadsheet, a new edition automatically becomes available to subscribers.
  148. Another user may choose to update an edition only upon request. This update mode might be useful for a user who creates a publisher within a word-processing application for a quarterly sales report. The user incrementally updates the sales report throughout the entire quarter, but does not want this information to be available to subscribers until the end of the quarter. Only at the end of each quarter does the user specifically request to update the edition and make it available to any subscribers.
  149. To create a subscriber within a document, the user places the insertion point and chooses Subscribe To from the Edit menu. Figure 1-4 shows the dialog box that your application should display when the user chooses Subscribe To. 
  150. The subscriber dialog box
  151. The subscriber dialog box also uses the extended interface of the standard file dialog box introduced with system software version 7.0. Initially, the dialog box should highlight the name of the last edition published or subscribed to. This allows a user to create a publisher and immediately subscribe to its edition.
  152. A subscriber receives its data from a single edition. By default, your application should automatically update a document containing a subscriber whenever a new edition is available. You also need to provide the user with the choice of receiving the latest edition manually (that is, only when the user specifically requests it). You can provide these options by using the subscriber options dialog box described later in “Using Publisher and Subscriber Options.”
  153. For example, one user may choose to automatically receive new editions as they become available. This update mode is useful for a user who subscribes to information from an edition that consists of daily sales figures. This user automatically acquires each version of the sales information as it becomes available.
  154. Another user may choose to receive a new edition only upon request. This update mode is useful for a user who creates a subscriber to an edition that consists of graphics data (such as a company logo). The user may require only periodic versions of the logo and not need frequent updates. In this case, your application should only update the subscriber with a new edition when the user specifically requests it.
  155. A user can select, cut, copy, or paste an entire subscriber. Although the contents of the subscriber as a whole can be modified, a user cannot edit portions of a subscriber. For example, a user can underline or italicize the entire subscriber text, but cannot delete a sentence or rotate a single graphical object. This restriction protects the user from losing changes to a subscriber when a new edition arrives. Remember that, as a default, new editions should automatically update a subscriber. Any changes that a user made to the subscriber text would have to be reapplied by the user when the new edition arrives. See “Modifying a Subscriber” later in this chapter for further information.
  156. A single document can contain any number or combination of publishers and subscribers. Figure 1-5 shows an example of a document that contains two publishers and one subscriber (and their corresponding editions). Remember that data always flows in one direction, from publisher to edition to subscriber. The “Concert flyer” document contains a publisher that is subscribed to by the “Benefit concert” document. The “Concert flyer” document also subscribes to a portion of the “Pianos & palm trees” document. In addition, the “Concert flyer” document as a whole is subscribed to by the “Sample flyer” document. 
  157. A document and its corresponding editions
  158. You should distinguish each selected publisher and subscriber within a document with a border. Display a publisher border as 3 pixels wide with 50 percent gray lines, and display a subscriber border as 3 pixels wide with 75 percent gray lines. A rectangle of one white pixel should separate the data from the border itself. Borders should be drawn outside the contents of publishers and subscribers so that data is not obscured. See Figure 1-6 for an illustration of the borders as they appear on screen. See “Displaying Publisher and Subscriber Borders” later in this chapter for detailed information on how to implement borders for specific applications. 
  159. Figure 1-6 shows a document containing a publisher and a document containing a subscriber, with borders displayed for each.
  160. Borders for publishers and subscribers should behave like the borders of 'PICT' graphics within a word-processing document. Your application should display a border whenever the user clicks within the content area of a publisher or a subscriber. Your application should hide the border whenever the user clicks outside the content area. See “Displaying Publisher and Subscriber Borders” later in this chapter for detailed information on how to implement borders for specific applications. 
  161. Publisher and subscriber borders
  162. You also need to support the standard Edition Manager menu commands in the Edit menu. These menu items include
  163. n    Create Publisher…
  164. n    Subscribe To…
  165. n    Publisher/Subscriber Options…
  166. n    Show/Hide Borders (optional)
  167. n    Stop All Editions (optional)
  168. Use a dotted line to separate the Edition Manager menu commands from the standard Edit menu commands Cut, Copy, and Paste. Figure 1-7 shows the standard Edition Manager menu commands.
  169. Edition Manager commands in the Edit menu
  170. The Subscriber Options menu command should toggle with the Publisher Options menu command. When a user selects a subscriber, the Subscriber Options menu command should appear in the menu and when a user selects a publisher, the Publisher Options menu command should appear in the menu. In addition, you may support a Show Borders menu command that toggles with Hide Borders to display or hide all publishers and subscriber borders within documents. You may also support a Stop All Editions menu command to provide a method for temporarily suspending all update activity in a document. When the user chooses this command, you should place a checkmark next to it. You should also stop all publishers from sending data to editions and all subscribers from receiving new editions. When the user chooses this command again, remove the checkmark and update any subscribers that are set up to receive new editions automatically.
  171. If you find that you need all of the available space in the Edit menu for your application’s commands, you may create a hierarchical menu for the Edition Manager menu commands. If you choose to implement this structure, you should allow users to access the Edition Manager menu commands through a Publishing menu command in the Edit menu. Because this menu structure is not as accessible to users, you should implement it only if you have no other alternative.
  172. Figure 1-8 shows the Edition Manager menu commands in a hierarchical menu structure.
  173. Edition Manager commands under the Publishing menu command
  174. For each publisher or subscriber within an open document, you must have a section record and an alias record. The section record contains a time stamp that records the version of the data that resides in the section. The section record also identifies the section as either a publisher or subscriber, and it establishes a unique identity for each publisher or subscriber. The section record does not contain the data within the section. The alias record is a reference to the edition container from the document that contains the corresponding publisher or subscriber section. 
  175. There are special options associated with publishers and subscribers within documents. Your application can use the publisher and subscriber options dialog boxes provided by the Edition Manager to make these choices available to the user. For example, a user can select Open Publisher within the subscriber options dialog box to access the document containing the publisher. Your application can also allow a user to cancel subscribers or publishers within documents, specify when to update an edition from a publisher, or specify when to update a subscriber with a new edition. These options are described later in this chapter.
  176. 1The Edition Manager
  177. Using The Edition Manager
  178. This section describes how your application can 
  179. n    receive Apple events from the Edition Manager
  180. n    set up a section record and alias record for open documents containing sections
  181. n    save a document that contains sections
  182. n    open a document that contains sections
  183. n    read and write sections
  184. n    create a publisher within a document, create its edition container, and write data to it
  185. n    create a subscriber within a document and read its data from an edition
  186. To begin, you must determine whether the Edition Manager is available on your system by using the Gestalt function. The Gestalt selector is gestaltEditionMgrAttr ('edtn'). If the response parameter returns 1 in the bit defined by the gestaltEditionMgrPresent constant (bit 0), the Edition Manager is present. 
  187. If the Edition Manager is present, load it into memory using the InitEditionPack function. This function determines whether your machine has enough space in the system heap for the Edition Manager to operate.
  188. err := InitEditionPack;
  189. If the InitEditionPack function returns noErr, you have enough space to load the package. If you do not have enough space, the application can either terminate itself or continue with the Edition Manager functionality disabled.
  190. Receiving Apple Events From the Edition Manager
  191. Applications that use the Edition Manager must support Apple events. This requires that your application support the required Open Documents event and Apple events sent by the Edition Manager. See the Apple Event Manager chapter in this volume for information on Apple events. 
  192. Apple events sent by the Edition Manager arrive as high-level events. The EventRecord data type defines the event record.
  193. TYPE EventRecord =
  194.     RECORD
  195.         what:                Integer;                {kHighLevelEvent}
  196.         message:                LongInt;                {'sect'}
  197.         when:                LongInt;    
  198.         where:                Point;                {'read', 'writ', 'cncl', }                 
  199.                                         { 'scrl'}
  200.         modifiers:                Integer;    
  201.     END;
  202. The Edition Manager can send the following Apple events:
  203. n    Section Read events ('sect' 'read')
  204. n    Section Write events ('sect' 'writ')
  205. n    Section Cancel events ('sect' 'cncl')
  206. n    Section Scroll events ('sect' 'scrl')
  207. Each time your application creates a publisher or a subscriber, the Edition Manager registers its section. When an edition is updated, the Edition Manager scans its list to locate registered subscribers. For each registered subscriber that is set up to receive updated editions automatically, your application receives a Section Read event. 
  208. If the Edition Manager discovers that an edition file is missing while registering a publisher, it creates a new edition file and sends the publisher a Section Write event. 
  209. When you receive a Section Cancel event, you need to cancel the specified section. Note that the current Edition Manager does not send you Section Cancel events, but you do need to provide a handler for future expansion.
  210. If the user selects a subscriber within a document and then selects Open Publisher in the subscriber options dialog box, the publishing application receives the Open Documents event and opens the document containing the publisher. The publishing application also receives a Section Scroll event. Scroll to the location of the publisher, display this section on the user’s screen, and turn on its border. 
  211. See “Opening and Closing a Document Containing Sections” later in this chapter for detailed information on registering and unregistering a section and writing data to an edition. See “Using Publisher and Subscriber Options” later in this chapter for information on publisher and subscriber options.
  212. After receiving an Apple event sent by the Edition Manager, use the Apple Event Manager to extract the section handle. In addition, you must also call the IsRegisteredSection function to determine whether the section is registered. It is possible (due to a race condition) to receive an event for a section that you recently disposed of or unregistered. One way to ensure that an event corresponds to a valid section is to call the IsRegisteredSection function after you receive an event. The Apple Event Manager chapter in this volume provides detailed information on Apple Event Manager routines. 
  213. err := IsRegisteredSection (sectionH);
  214. Listing 1-1 illustrates how to use the Apple Event Manager and install an event handler to handle Section Read events. You can write similar code for Section Write events, Section Scroll events, and Section Cancel events. 
  215. Accepting Section Read events and verifying if a section is registered
  216. {The following goes in your initialization code.}
  217. MyErr := AEInstallEventHandler(sectionEventMsgClass {'sect'}, 
  218.                                              sectionReadMsgID {'read'}, 
  219.                                            @MyHandleSectionReadEvent, 0,
  220.                                          FALSE);
  221.  
  222. {This is the routine the Apple Event Manager calls when a } 
  223. { Section Read event arrives.}
  224.  
  225. FUNCTION MyHandleSectionReadEvent(theAppleEvent, 
  226.                                              reply: AppleEvent; 
  227.                                                   refCon: LongInt) : OSErr;
  228. VAR
  229.     getErr:                OSErr;
  230.     sectionH:                SectionHandle;
  231. BEGIN
  232.     {Get section handle out of Apple event message buffer.}
  233.     getErr := GetSectionHandleFromEvent(theAppleEvent, sectionH);
  234.  
  235.     IF getErr = noErr THEN
  236.     BEGIN
  237.         {Do nothing if section is not registered.}
  238.         IF IsRegisteredSection(sectionH) = noErr
  239.             THEN MyHandleSectionReadEvent := DoSectionRead(sectionH);
  240.     END ELSE
  241.     BEGIN
  242.         MyHandleSectionReadEvent := getErr;
  243.     END;
  244. END; {MyHandleSectionReadEvent}
  245.  
  246. {The following routine should read in subscriber data and update }
  247. { its display.}
  248. FUNCTION DoSectionRead(subscriber: SectionHandle) : OSErr;
  249. BEGIN
  250.             {Your code here.}
  251. END;                    {DoSectionRead}
  252. {This is part of your Apple event–handling code.}
  253. FUNCTION GetSectionHandleFromEvent(theAppleEvent: AppleEvent; 
  254.                                                 VAR sectionH: SectionHandle) :
  255.                                                 OSErr;
  256. VAR
  257.     ignoreType:                    DescType;
  258.     ignoreSize:                    Size;
  259. BEGIN
  260.     {Parse section handle out of message buffer.}
  261.     GetSectionHandleFromEvent 
  262.         := AEGetParamPtr( theAppleEvent,                                                {event to parse}
  263.                                   keyDirectObject,                        {Look for direct }
  264.                                                         { object.}
  265.                                   typeSectionH,                         {Want a SectionHandle }
  266.                                                         { type.}
  267.                                   ignoreType,                        {Ignore type it could }
  268.                                                         { get.}
  269.                                  @sectionH,                         {Put SectionHandle }
  270.                                                         { here.}
  271.                                  SizeOf(sectionH),                        {size of storage for } 
  272.                                                         { SectionHandle}
  273.                                  ignoreSize);                        {Ignore storage it }
  274.                                                         { used.}
  275. END; {GetSectionHandleFromEvent} 
  276. Creating the Section Record and Alias Record
  277. Your application is responsible for creating a section record and an alias record for each publisher and subscriber section within an open document. 
  278. The section record identifies each section as a publisher or subscriber and provides identification for each section. The section record does not contain the data within the section; it describes the attributes of the section. Your application must provide its own method for associating the data within a section with its section record. Your application is also responsible for saving the data in the section. 
  279. The alias field of the section record contains a handle to its alias record. The alias record is a reference to the edition container from the document which contains the publisher or subscriber section. You should be familiar with the Alias Manager’s conventions for creating alias records and identifying files, folders, and volumes to locate files that have been moved, copied, or restored from backup. 
  280. When a user saves a document, your application should store all section records and alias records in the resource fork. Corresponding section records and alias records should have the same resource ID. This allows compatibility for future changes.
  281. Figure 1-9 shows a document containing a publisher and subscriber, and the corresponding section records and alias records.
  282. The SectionRecord data type defines the section record. A section record contains information to identify the data contained within a section as a publisher or a subscriber, a time stamp to record the last modification of the section, and unique identification for each section.
  283. A document with a publisher and subscriber and its resource fork
  284. TYPE SectionRecord = 
  285.     RECORD
  286.         version:                    SignedByte;                    {always 1 in 7.0}
  287.         kind:                    SectionType;                    {publisher or subscriber}
  288.         mode:                    UpdateMode;                    {automatic or manual}
  289.         mdDate:                    TimeStamp;                    {last change in document}
  290.         sectionID:                    LongInt;                    {application-specific, }
  291.                                                 { unique per document}
  292.         refCon:                    LongInt;                    {application-specific}
  293.         alias:                    AliasHandle;                    {handle to alias record}
  294.  
  295.         {The following fields are private and are set up by the }
  296.         { RegisterSection function described later within this }
  297.         { chapter. Do not modify the private fields.}
  298.  
  299.         subPart:                    LongInt;                    {private}
  300.         nextSection:                    SectionHandle;                    {private, do not use as a }
  301.                                                 { linked list}
  302.         controlBlock:                    Handle;                    {may be used for comparison }
  303.                                                 { only}
  304.         refNum:                    EditionRefNum;                    {private}
  305. END;
  306. version    Indicates the version of the section record, currently $01. 
  307. kind    Defines the section type as either publisher or subscriber with the stPublisher or stSubscriber constant. 
  308. mode    Indicates if editions are updated automatically or manually. 
  309. mdDate    Indicates which version (modification date) of the section’s contents is contained within the publisher or subscriber. The mdDate is set to 0 when you create a new subscriber section, and is set to the current time when you create a new publisher. Be sure to update this field each time publisher data is modified. The section’s modification date is compared to the edition’s modification date to determine whether the section and the edition contain the same data. The section modification date is displayed in the publisher and subscriber options dialog boxes. See “Closing an Edition” later in this chapter for detailed information. 
  310. sectionID    Provides a unique number for each section within a document. A simple way to implement this is to create a counter for each document that is saved to disk with the document. The counter should start at 1. The section ID is currently used as a tie breaker in the GoToPublisher function when there are multiple publishers to the same edition in a single document. The section ID should not be 0 or –1. See “Duplicating Publishers and Subscribers” later in this chapter for information on multiple publishers. 
  311. refCon    Reference constant available for application-specific use. 
  312. alias    Contains a handle to the alias record for a particular section within a document. 
  313. Whenever the user creates a publisher or subscriber, call the NewSection function to create the section record and the alias record.
  314. err := NewSection (container, sectionDocument, kind, sectionID, 
  315.                             initialMode, sectionH);
  316. The NewSection function creates a new section record (either publisher or subscriber), indicates whether editions are updated automatically or manually, sets the modification date, and creates an alias record from the document containing the section to the edition container. 
  317. The sectionDocument parameter can be NIL if your current document has never been saved. Use the AssociateSection function to update the alias record of a registered section when the user names or renames a document by choosing Save As from the File menu. If you are creating a subscriber with the initialMode parameter set to receive new editions automatically, your application receives a Section Read event each time a new edition becomes available for this subscriber.
  318. If an error is encountered, the sectionH parameter is set to NIL. If not, sectionH contains the handle to the allocated section record.
  319. Set the initialMode parameter to the update mode for each subscriber and publisher created. You can specify the update mode using these constants: 
  320. CONST            sumAutomatic                    = 0;            {subscriber receives new }                        
  321.                                             { editions automatically}
  322.             sumManual                    = 1;            {subscriber receives new }
  323.                                             { editions manually}
  324.             pumOnSave                    = 0;            {publisher sends new }
  325.                                             { editions on save}    
  326.             pumManual                    = 1;            {publisher does not send }
  327.                                             { new editions until user }
  328.                                              { request}
  329. See “Using Publisher and Subscriber Options” later in this chapter for detailed information on update modes for publishers and subscribers. 
  330. Saving a Document Containing Sections
  331. When saving a document that contains sections, you should write out each section record as a resource of type 'sect' and write out each alias record as a resource of type 'alis' with the same ID as the section record. See the Resource Manager chapters in Volume I and this volume for detailed information on resources. 
  332. If a user closes a document that contains newly created publishers without attempting to save its contents, you should display an alert box similar to the one shown in Figure 1-10. 
  333. The new publisher alert box
  334. If you keep the section records and alias records for each publisher and subscriber as resources, you can use the ChangedResource or WriteResource function. If you detach the section records and alias records from each section, you need to clone the handles and use the AddResource function. See the Resource Manager chapter in Volume V for detailed information on the ChangedResource, WriteResource, and AddResource functions.
  335. Use the PBExchangeFiles function to ensure that each time you save a document that contains sections, the file ID remains the same. Saving a file typically involves creating a new file (with a temporary name), writing data to it, closing it, and then deleting the original file that you are replacing. You rename the temporary file with the original filename, which leads to a new file ID. The PBExchangeFiles function swaps the contents of the two files (even if they are open) by getting both catalog entries and swapping the allocation pointers. If the files are open, the file control block (FCB) is updated so that the reference numbers still access the same contents (under a new name). See the File Manager chapter in this volume for detailed information on the PBExchangeFiles function.
  336. Listing 1-2 illustrates how to save a file that contains sections. As described earlier, you should write out the eligible section records and alias records as resources to allow for future compatibility. There are several different techniques for saving or adding resources; this listing illustrates one technique. The section handles are still valid after using the AddResource function because this listing illustrates just saving, not closing, the file.
  337. Before you write out sections, you need to see if any publisher sections share the same control block. Publishers that share the same control block share the same edition.
  338. If a user creates an identical copy of a file by choosing Save As from the File menu and does not make any changes to this new file, you simply use the AssociateSection function to indicate to the Edition Manager which document a section is located in. 
  339. Saving a document containing sections
  340. PROCEDURE SaveDocument(thisDocument: MyDocumentInfoPtr;
  341.                               numberOfSections: Integer);
  342.  
  343. VAR
  344.         aSectionH:                        SectionHandle;
  345.         copiedSectionH:                        Handle;
  346.         copiedAliasH:                        Handle;
  347.         resID:                        Integer;
  348.         thisone:                        Integer;
  349.  
  350. BEGIN
  351.         {Write contents of publishers that need to be written }
  352.         { during save. The GetSectionAliasPair function returns }
  353.         { a handle and resID to a section. The CheckForDataChanged }
  354.         { function returns TRUE if the data in the section has }
  355.         { changed. }
  356.         FOR thisone := 1 TO numberOfSections DO
  357.         BEGIN
  358.             aSectionH := GetSectionAliasPair(thisDocument, thisone, resID);
  359.             IF (aSectionH^^.kind = stPublisher) &
  360.                 (aSectionH^^.mode = pumOnSave) &
  361.                 (CheckForDataChanged(aSectionH))
  362.             THEN DoWriteEdition(aSectionH, thisDocument);
  363.         END; {for}
  364.         {Set the curResFile to be the resource fork of thisDocument.}
  365.         UseResFile(thisDocument^.resForkRefNum);
  366.     
  367.         {Write all section and alias records to the document.}
  368.         FOR thisone := 1 TO numberOfSections DO
  369.         BEGIN
  370.             {Given an index, get the next section handle and resID }
  371.             { from your internal list of sections for this file.}
  372.             aSectionH := GetSectionAliasPair(thisDocument, thisone, resID);
  373.             {Check for duplication of control block values.}
  374.             CheckForDupes(thisDocument, numberOfSections);
  375.  
  376. {Save section record to disk.}
  377.             copiedSectionH := Handle(aSectionH)
  378.             HandToHand(copiedSectionH);
  379.             AddResource(copiedSectionH, rSectionType, resID, '');
  380.  
  381.             {Save alias record to disk.}
  382.             copiedAliasH := Handle(aSectionH^^.alias);
  383.             HandToHand(copiedAliasH);
  384.             AddResource(copiedSectionH, rAliasType, resID, '');
  385.         END; {for}
  386.  
  387.           {Write rest of document to disk.}
  388. END; {SaveDocument}
  389. Opening and Closing a Document Containing Sections
  390. When opening a document that contains sections, your application should use the GetResource function to get the section record and the alias record for each publisher and subscriber. Set the alias field of the section record to be the handle to the alias. See the Resource Manager chapter in Volume I for detailed information on the GetResource function. 
  391. You also need to register each section using the RegisterSection function. The RegisterSection function informs the Edition Manager that a section exists. 
  392. err := RegisterSection(sectionDocument, sectionH,aliasWasUpdated);
  393. The RegisterSection function adds the section record to the Edition Manager’s list of registered sections. This function assumes that the alias field of each section record is a handle to the alias record. The alias record is a reference to the edition container from the section’s document. If the RegisterSection function successfully locates the edition container for a particular section, the section is registered through a shared control block. The control block is a private field in the section record. 
  394. If the RegisterSection function cannot find the edition container for a particular subscriber, RegisterSection returns the containerNotFoundWrn result code. If the RegisterSection function cannot find the edition container for a particular publisher, RegisterSection creates an empty edition container for the publisher in the last place the edition was located. The Edition Manager sends your application a Section Write event for that section. 
  395. When a user attempts to open a document that contains multiple publishers to the same edition, you should warn the user by displaying an alert box (see “Duplicating Publishers and Subscribers” later in this chapter).
  396. When a user opens a document that contains a subscriber (with an update mode set to automatic), receives a new edition, and then closes the document without making any changes to the file, you should update the document and simply allow the user to close it. You do not need to prompt the user to save changes to the file.
  397. When closing a document that contains sections, you must unregister each section (using the UnRegisterSection function) and dispose of each corresponding section record and alias record. 
  398. err := UnRegisterSection (sectionH);
  399. The UnRegisterSection function removes the section record from the list of registered sections and unlinks itself from the shared control block.
  400. Listing 1-3 illustrates how to open an existing file that contains sections. As described earlier, you should retrieve the section and alias resources, connect the pair through the alias field of the section record, and register the section with the Edition Manager. There are many different techniques for retrieving resources; this listing shows one technique. If an alias was out of date and was updated by the Alias Manager during the resolve, the Edition Manager sets the aliasWasUpdated parameter of the RegisterSection function to TRUE. This means that you should save the document. Additionally, your application must maintain its own list of registered sections for each open document that contains sections. You use this list to write out new editions for updated publishers within a document.
  401. Opening a document containing sections
  402. PROCEDURE OpenExistingDocument(thisDocument: MyDocumentInfoPtr);
  403.  
  404. VAR
  405.     sectionH:                            SectionHandle;
  406.     aliasH:                            AliasHandle;
  407.     aliasWasUpdated:                            Boolean;
  408.     registerErr:                            OSErr;
  409.     resID:                            Integer;
  410.     thisone:                            Integer;
  411.     numberOfSections:                            Integer;
  412.     aName:                            Str255;
  413.  
  414. BEGIN
  415.     {Set the curResFile to be the resource fork of thisDocument.}
  416.     UseResFile(thisDocument^.resForkRefNum);
  417.     {Find out the number of section resources.}
  418.     numberOfSections := Count1Resources(rSectionType);
  419.  
  420.     {In determining the number of section/alias resource pairs to } 
  421.     { get, this code only loops for as many sections it finds. }
  422.     { It is unusual to have more section resources than alias }
  423.     { resources. Your code may want to check this and handle it }
  424.     { appropriately. You now have a count of the number of }
  425.     { section/            alias resource pairs to get. Loop to get them, }
  426.     { connect them, and register the section.}
  427.     FOR thisone := 1 TO numberOfSections DO
  428.     BEGIN
  429.         sectionH := SectionHandle(Get1IndResource(rSectionType,
  430.                                             thisone));
  431.         {If sectionH is NIL, something could be wrong with the }
  432.         { file. Be sure to check for this.}
  433.  
  434.         {Get the resource ID of the section and use this to get }
  435.         { the alias with the same resource ID.}
  436.         GetResInfo(Handle(sectionH), resID, rSectionType, aName);
  437.         DetachResource(Handle(sectionH));
  438.         {Detaching is not necessary, but it is convenient.}
  439.  
  440.         aliasH := AliasHandle(Get1Resource(rAliasType, resID));
  441.         {If aliasH is NIL, then there could be something wrong }
  442.         { with the file. Be sure to check for this.}
  443.  
  444.         DetachResource(Handle(aliasH));
  445.         {Detaching is not necessary, but it is convenient.}
  446.  
  447.         {Connect section and alias together.}
  448.         sectionH^^.alias := aliasH;
  449.  
  450.         {Register the section.}
  451.         registerErr := RegisterSection(thisDocument^.fileSpec,
  452.                                                        sectionH, aliasWasUpdated);
  453.  
  454.         {The RegisterSection function may return an error if }
  455.         { a section is not registered. This is not a fatal error. }
  456.         { Continue looping to register remaining sections.}                            
  457.         {Add this section/alias pair to your internal bookkeeping. }
  458.         { The AddSectionAliasPair is a routine to accomplish this.}
  459.         MyAddSectionAliasPair(thisDocument, sectionH, resID);
  460.  
  461.         {If the alias has changed, make note of this. It is }
  462.         { important to know this when you save. AliasHasChanged is }                        
  463.         { a routine that will do this.}
  464.         IF aliasWasUpdated THEN AliasHasChanged(sectionH);
  465.     END; {for}
  466. END;  {OpenExistingDocument}
  467. Reading and Writing a Section
  468. Your application writes publisher data to an edition. New publisher data replaces the previous contents of the edition, making the previous edition information irretrievable. Your application reads data from an edition for each subscriber within a document. 
  469. The following sections describe how to
  470. n    use different formats to write to or read from an edition
  471. n    open an edition to initiate writing or reading
  472. n    set a format mark
  473. n    write to or read from an edition
  474. n    close an edition after successfully writing or reading data
  475. Formats in an Edition
  476. You can write data to an edition in several different formats. These formats are the same as Clipboard formats. Clipboard formats are indicated by a four-character tag. 
  477. Typically, when a user copies data, you identify the Clipboard formats and then write the data to scrap. With the Edition Manager, when a user decides to publish data, you identify the Clipboard formats and then write the data to an edition. You can write multiple formats of the same data. 
  478. For an edition, you should write your preferred formats first. In general, to write data to an edition, your application should use either 'TEXT' format or 'PICT' format. This allows your application to share data with most other applications. To subscribe to an edition, your application should be able to read both 'TEXT' and 'PICT' files. In addition, your application can write any other private formats that you want to support.
  479. Clipboard formats are described in the Scrap Manager chapter in Volume I. 
  480. A few special formats are defined as constants.
  481. CONST        kPublisherDocAliasFormat                                    = 'alis';    {alias record from the }
  482.                                                         { edition to publisher}
  483. kPreviewFormat                                            = 'prvw';    {'PICT' thumbnail }
  484.                                                         { sketch}
  485. kFormatListFormat                                            = 'fmts';    {lists all available }
  486.                                                         { formats}
  487. The kPublisherDocAliasFormat ('alis') format is written by the Edition Manager. It is an alias record from the edition to the publisher’s document. Appended to the end of the alias is the section ID of the publisher, which the Edition Manager uses to distinguish between multiple publishers to a single edition. You should discourage users from making multiple copies of the same publisher. See “Duplicating Publishers and Subscribers” later in this chapter for detailed information.
  488. The kPreviewFormat ('prvw') format should be written by any application that publishes large amounts of data that may be slow to draw a preview. This format holds a preview of the edition data that is displayed in the preview area of the subscriber dialog box. This format is actually a 'PICT' file that is generated by the publishing application and displays well in a rectangle of 120 by 120 pixels. You can also use this 'PICT' file to display subscriber data within a document (to save space). 
  489. To draw a preview in the 'prvw' format, the Edition Manager calls DrawPicture with a 120 by 120 rectangle. To draw a preview in the 'PICT' format, the Edition Manager examines the picture’s bounding rectangle and calls DrawPicture with a rectangle that scales the picture proportionally and centers it in a 120 by 120 area. 
  490. The kFormatListFormat ('fmts') format is a virtual format that is read but never written. It is a list of all the formats and their lengths. Applications can use this format in place of the EditionHasFormat function (described in “Choosing Which Edition Format to Read” later in this chapter), which provides a procedural interface to determine which formats are available.
  491. If your application can read two or more of the available formats, use 'fmts' to determine the priority of these formats for a particular edition. The order of 'fmts' reflects the order in which the formats were written.
  492. The FormatsAvailable data type defines a record for the 'fmts' format. 
  493. TYPE FormatsAvailable = ARRAY[0..0] OF
  494.     RECORD
  495.         theType:                FormatType;                    {format type for an edition}
  496.         theLength:                LongInt;                    {length of edition format }
  497.                                             { type}
  498.     END;
  499. For example, an edition container may have a format type 'TEXT' of length 100, and a format type 'styl' of length 32. A subscriber to this edition can open it and then read the format type 'fmts' to list all available formats. In this example, it returns 16 bytes: 'TEXT' $00000064 'styl' $00000020.
  500. Opening an Edition
  501. For a publisher, use the OpenNewEdition function to initiate the writing of data to an edition.
  502. err := OpenNewEdition (publisherSectionH, fdCreator,
  503.                               publisherSectionDocument, refNum);
  504. The publisherSectionH parameter is the publisher section that you are writing to the edition. The fdCreator parameter is the Finder<Superscript\>\xaa  creator type of the new edition icon.
  505. The publisherSectionDocument parameter is the document that contains the publisher. This parameter is used to create an alias from the edition to the publisher’s document. If you pass NIL for publisherSectionDocument, an alias is not made in the edition file. The refNum parameter returns the reference number for the edition. 
  506. For a subscriber, use the OpenEdition function to initiate the reading of data from an edition.
  507. err := OpenEdition (subscriberSectionH, refNum); 
  508. The subscriberSectionH parameter is a handle to the section record for a given section. The refNum parameter returns the reference number for the edition.
  509. The user may rename or move the edition in the Finder. Before writing to or reading data from an edition, the Edition Manager verifies the name of the edition. This process is referred to as synching or synchronization. Synching ensures that the Edition Manager’s existing edition names correspond to the Finder’s existing edition names by updating the control block. 
  510. Format Marks
  511. Each format has its own mark. The mark indicates the next position of a read or write operation. Initially, a mark automatically defaults to 0. After reading or writing data, the format mark is set past the last position written to or read from. The mark is similar to the File Manager’s current read or write position marker for a data fork. Any time that an edition is open (after calling the OpenEdition or the OpenNewEdition function), any of the marks for each format can be queried or set. 
  512. To set the current mark for a section format to a new location, use the SetEditionFormatMark function. 
  513. err := SetEditionFormatMark (whichEdition, whichFormat,
  514.                                       setMarkTo); 
  515. To find where a current mark is for a format in an edition file, use the GetEditionFormatMark function. 
  516. err := GetEditionFormatMark (whichEdition, whichFormat,
  517.                                       currentMark); 
  518. Reading and Writing Edition Data
  519. With the Edition Manager, you can read or write data a few bytes at a time instead of putting data into one block as the Scrap Manager does. This model is similar to the data fork of a Macintosh file. You can read sequentially by setting the mark to 0 and repeatedly calling read, or you can jump to a specific offset by setting the mark there. The Edition Manager also adds the capability to stream multiple formats by keeping a separate mark for each format. This allows you to write a few bytes of one format and then write a few bytes of another format, and so forth.
  520. Once you have opened the edition container for a particular publisher, you can begin writing data to the edition. Use the WriteEdition function to write publisher data to an edition. 
  521. err := WriteEdition (whichEdition, whichFormat, buffPtr, buffLen);
  522. The WriteEdition function writes the specified format (beginning at the current mark for that format type) from the buffer pointed to by the buffPtr parameter up to buffLen bytes. 
  523. After you open the edition container for a subscriber and determine which formats to read, use the ReadEdition function to read edition data. 
  524. err := ReadEdition (whichEdition, whichFormat, buffPtr, buffLen);
  525. The ReadEdition function reads the data with the specified format (whichFormat) from the edition into the buffer. The ReadEdition function begins reading at the current mark for that format and continues to read up to buffLen bytes. The actual number of bytes read is returned in the buffLen parameter. Once the buffLen parameter returns a value smaller than the value you have specified, there is no additional data to read, and the ReadEdition function returns a noErr result code. 
  526. Closing an Edition
  527. When you are done writing to or reading data from an edition, call the CloseEdition function. 
  528. err := CloseEdition (whichEdition, successful);
  529. Each time a user edits a publisher within a document, you must update the modification date in the section record (even if the data is not yet written). When the update mode is set to Manually, the user can compare the modification dates for a publisher and its edition in the publisher options dialog box. One modification date indicates when the publisher last wrote data to the edition, and the other modification date indicates when the publisher section was last edited. 
  530. If the successful parameter for a publisher is TRUE, the CloseEdition function makes the newly written data available to subscribers and sets the modification date in the mdDate field of the edition to correspond to the modification date of the publisher’s section record. If the two dates differ, the Edition Manager sends a Section Read event to all current subscribers. 
  531. If the successful parameter for a subscriber is TRUE, the CloseEdition function sets the modification date of the subscriber’s section record to correspond to the modification date of the edition.
  532. If you cannot successfully read from or write data to an edition, set the successful parameter to FALSE. For a publisher, data is not written to the edition, but it should still be saved with the document that contains the section. When the document is next saved, data can then be written to the edition. See “Closing an Edition After Reading or Writing” later in this chapter for additional information on the CloseEdition function. 
  533. Creating a Publisher
  534. You need to support a Create Publisher menu command in the Edit menu. When a user selects a portion of a document and chooses Create Publisher from this menu, you should display the publisher dialog box on the user’s screen. The Create Publisher menu command should remain dimmed until the user selects a portion of a document. 
  535. Use the NewPublisherDialog function to display the publisher dialog box on the user’s screen. This function is similar to the CustomPutFile procedure described in the Standard File Package chapter in this volume. 
  536. err := NewPublisherDialog (reply);
  537. The dialog box contains space for a preview (a thumbnail sketch) of the edition and a space for the user to type in the name of the edition in which to write the publisher data. Figure 1-11 illustrates a sample publisher dialog box.
  538. A sample publisher dialog box
  539. The NewPublisherDialog function displays the preview (provided by your application), a text box with the default name of the edition (provided by your application), and handles all user input until the user clicks Publish or Cancel.
  540. You pass a new publisher reply record as a parameter to the NewPublisherDialog function.
  541. TYPE NewPublisherReply = 
  542.     RECORD
  543.         canceled:                    Boolean;                    {user canceled dialog box}
  544.         replacing:                    Boolean;                    {user chose existing }
  545.                                                 { filename for an edition}
  546.         usePart:                    Boolean;                    {always FALSE in version 7.0}
  547.         preview:                    Handle;                    {handle to 'prvw', 'PICT', }
  548.                                                 { 'TEXT', or 'snd' data}
  549.         previewFormat:                    FormatType;                    {type of preview}
  550.         container:                    EditionContainerSpec;        
  551.                                                 {edition chosen}
  552.     END;
  553. You fill in the usePart, preview, previewFormat, and container fields of the new publisher reply record.
  554. Always set the usePart field to FALSE. The preview field contains either NIL or the data to display in the preview. The previewFormat field should contain 'PICT', 'TEXT', or 'prvw'. 
  555. Set the container field to be the default name and folder for the edition. The default name should reflect the data contained in the publisher. For example, if a user publishes a bar chart of sales information entitled “sales data,” then the default name for the edition could also be “sales data.” Otherwise, you should use the document name followed by a hyphen (-) and a number to establish uniqueness. For example, your default name could be “January Totals - 3.”
  556. If the document has not been saved, the default name should be “untitled edition <n>” where n is a number to establish uniqueness. The default folder should be the same as the edition for the last publisher created in the same document. If this is the first publisher in the document, the default folder should be the same folder that the document is in. 
  557. The canceled field of the new publisher reply record indicates whether the user canceled from the dialog box. The replacing field indicates that the user chose to replace an existing edition file. If replacing returns FALSE, call the CreateEditionContainerFile function to create an edition file. 
  558. The container field is of data type EditionContainerSpec.
  559. TYPE EditionContainerSpec = 
  560.     RECORD
  561.         theFile:                    FSSpec;                    {file containing edition }
  562.                                                 { data}
  563.         theFileScript:                    ScriptCode;                    {script code of filename}
  564.         thePart:                    LongInt;                    {which part of file, }
  565.                                                 { always kPartsNotUsed}
  566.         thePartName:                    Str31;                    {not used in version 7.0}
  567.         thePartScript:                    ScriptCode;                    {not used in version 7.0}
  568.     END;
  569. The field theFile is of type FSSpec. See the File Manager chapter in this volume for further information on file system specification records.
  570. You identify the edition using a volume reference number, directory ID, and filename. When specifying an edition, follow the standard conventions described in the File Manager chapter of this volume.
  571. After filling in the fields of the new publisher reply record, pass it as a parameter to the NewPublisherDialog function, which displays the publisher dialog box. 
  572. err := NewPublisherDialog (reply);
  573. After displaying the publisher dialog box, use the CreateEditionContainerFile function to create the edition container, and then use NewSection function to create the section record and the alias record. See “Creating the Section Record and Alias Record” earlier in this chapter for detailed information.
  574. In response to the user selecting the Create Publisher menu item, this code illustrates how your application might set up the preview for the edition, set the default name for the edition container, and call an application-defined function (DoNewPublisher function) to display the publisher dialog box on the user’s screen. An application might call the DoNewPublisher function as a result of the user making a menu selection to create a publisher or in response to handling the Create Publisher event. See the Apple Event Manager chapter in this volume for an example handler that handles the Create Publisher event. 
  575. VAR
  576.     thisDocument:                             MyDocumentInfoPtr; 
  577.     promptForDialog:                             Boolean;
  578.     preview:                             Handle; 
  579.     previewFormat:                             FormatType; 
  580.     defaultLocation:                             EditionContainerSpec;
  581.  
  582. BEGIN
  583.     {Get a preview to show the user. The MyGetPreviewForSelection }
  584.     { function returns a handle to the preview.}
  585.     preview := MyGetPreviewForSelection(thisDocument);
  586.     previewFormat := 'TEXT';
  587.     defaultLocation := MyGetDefaultEditionSpec(thisDocument);
  588.     promptForDialog := TRUE;
  589.     myErr := DoNewPublisher(thisDocument, promptForDialog, preview, 
  590.                                     previewFormat, defaultLocation);
  591. END;
  592. Creating the Edition Container
  593. Use the CreateEditionContainerFile function to create an edition container to hold the publisher data.
  594. err := CreateEditionContainerFile (editionFile, fdCreator,
  595.                                               editionFileNameScript);
  596. This function creates an edition container. The edition container is empty (that is, it does not contain any formats) at this time.
  597. To create a customized icon for the edition container, put the creator signature of your application with the icon in your application’s bundle. See the Finder Interface chapter in this volume for additional information. Depending on the contents of the edition, the file type will be 'edtp' (for graphics), 'edtt' (for text), or 'edts' (for sound).
  598. After creating the edition container, use the NewSection function to create the section record and alias record for the section.
  599. Listing 1-4 illustrates how to create a publisher. The DoNewPublisher function shown in the listing is a function provided by an application. Note that an application might call the DoNewPublisher function as a result of the user making a menu selection to create a publisher or in response to handling the Create Publisher event. See the Apple Event Manager chapter in this volume for an example handler that handles the Create Publisher event.
  600. The parameters to the DoNewPublisher function include a pointer to information about the document, a Boolean value that indicates if the function should display the new publisher dialog box, the preview for the edition, the preview format, and an edition container.
  601. The function displays the publisher dialog box if requested, letting the user accept or change the name of the edition and the location where the edition should reside. Use the CreateEditionContainerFile function to create the edition with the given name and location. Use the NewSection function to create a new section for the publisher.
  602. After the section is created, you must write out the edition data. Be sure to add the newly created section to your list of sections for this document. There are several different techniques for creating publishers and unique IDs; this listing displays one technique. 
  603. Creating a publisher
  604. FUNCTION DoNewPublisher(thisDocument:                                                         MyDocumentInfoPtr;  
  605.                                 promptForDialog: Boolean; preview: Handle; 
  606.                                 previewFormat:                         FormatType; 
  607.                                 editionSpec:                         EditionContainerSpec) : OSErr;
  608. VAR
  609.         getLastErr, dialogErr:                                OSErr;
  610.         createErr, sectionErr:                                OSErr;
  611.         resID:                                Integer;
  612.         thisSectionH:                                SectionHandle;
  613.         reply:                                NewPublisherReply;
  614. BEGIN
  615.         {Set up info for new publisher reply record}
  616.         reply.replacing := FALSE;
  617.         reply.usePart := FALSE;
  618.         reply.preview := preview;
  619.         reply.previewFormat := previewFormat;
  620.         reply.container := editionSpec;
  621.         IF promptForDialog THEN 
  622.         BEGIN                                    {user interaction is allowed}
  623.                                             {Display dialog box and let user select.}
  624.             dialogErr := NewPublisherDialog(reply);
  625.             {Dispose of preview data handle.}
  626.             DisposHandle(reply.preview);
  627.             {There's usually no error returned here, but if there is, }
  628.             { then it makes no sense to continue with this operation.}
  629.             IF dialogErr <> noErr THEN MyErrHandler(dialogErr);
  630.             {Do nothing if user canceled.}
  631.             IF reply.canceled THEN 
  632.             BEGIN
  633.                 DoNewPublisher := userCanceledErr; 
  634.                 EXIT(DoNewPublisher);
  635.             END;
  636.         END;
  637.         {If user wants to replace an existing file, don't create one.}
  638.         IF NOT reply.replacing THEN
  639.         BEGIN
  640.             createErr := 
  641.                 CreateEditionContainerFile(reply.container.theFile, kAppSignature,
  642.                                                     reply.container.theFileScript);
  643.             {If the create failed, then this operation can't be completed}
  644.             IF createErr <> noErr THEN
  645.             BEGIN
  646.                 DoNewPublisher := errAEPermissionDenied;
  647.                 EXIT(DoNewPublisher);
  648.             END;
  649.         END;
  650.         {Advance counter to make a new unique sectionID for this }
  651.         { document. It is not required that you equate section IDs with }
  652.         { resources.}
  653.         thisDocument^.nextSectionID := thisDocument^.nextSectionID + 1;
  654.         {Create a publisher section.}
  655.         sectionErr := NewSection(reply.container,             
  656.                                          thisDocument^.fileSpecPtr,
  657.                                           stPublisher, thisDocument^.nextSectionID,
  658.                                           pumOnSave, thisSectionH);
  659.         IF (sectionErr <> noErr) & (sectionErr <> multiplePublisherWrn) & 
  660.             (sectionErr <> notThePublisherWrn) THEN
  661.             {If a new section could not be created, don't continue }
  662.             { with this operation. }
  663.             MyErrHandler(sectionErr);
  664.         resID := thisDocument^.nextSectionID;
  665.         {Add this section/alias pair to my internal bookkeeping. }
  666.         { The AddSectionAliasPair is a routine to accomplish this.}
  667.         AddSectionAliasPair(thisDocument, thisSectionH, resID);
  668.         {Write out first edition.}
  669.         DoWriteEdition(thisSectionH, thisDocument);
  670.         {Remember that the section and alias records need to be }
  671.         { saved as resources when the user saves the document.}
  672.         {Set the function result appropriately}
  673.         DoNewPublisher := MyGetLastError;
  674. END; {DoNewPublisher}
  675. Opening an Edition Container to Write Data
  676. Several routines are required to write (publish) data from a publisher to an edition container. Before writing data to an edition, you must use the OpenNewEdition function. This function should be used only for a publisher within a document. Use this function to initiate the writing of data to an edition. 
  677. err := OpenNewEdition (publisherSectionH, fdCreator,
  678.                               publisherSectionDocument, refNum);
  679. A user may try to save a document containing a publisher that is unable to write its data to an edition—because another publisher (that shares the same edition) is writing, another subscriber (that shares the same edition) is reading, or a publisher located on another computer is registered to the section. In such a case, you may decide to refrain from writing to the edition so that the user does not have to wait. You should also refrain from displaying an error to the user. The contents of the publisher are saved to disk with the document. The next time that the user saves, you can write the publisher data to the edition. You should discourage users from making multiple copies of the same publisher and pasting them in the same or other documents by displaying an alert box (see “Duplicating Publishers and Subscribers” later in this chapter). 
  680. If a user clicks Send Edition Now within the publisher options dialog box (to write publisher data to an edition manually), and the publisher is unable to write its data to its edition (for any of the reasons outlined above), you should display an error message. 
  681. After you are finished writing data to an edition, use the CloseEdition function to close the edition.
  682. Listing 1-5 illustrates how to write data to an edition. As described earlier, you must open the edition, write each format using the WriteEdition function, and close the edition using the CloseEdition function. This listing shows how to write text only. If the edition is written successfully, subscribers receive Section Read events. 
  683. Writing data to an edition
  684. PROCEDURE DoWriteEdition(thePublisher: SectionHandle);
  685. VAR
  686.     eRefNum:                    EditionRefNum;
  687.     openErr:                    OSErr;
  688.     writeErr:                    OSErr;
  689.     closeErr:                    OSErr;
  690.     thisDocument:                    MyDocumentInfoPtr;
  691.     textHandle:                    Handle;
  692. BEGIN
  693.     {Find out which document this section belongs to. }
  694.     { The FindDocument function accomplishes this.}
  695.     thisDocument := FindDocument(thePublisher);
  696.     {Open edition for writing.}
  697.     openErr := OpenNewEdition(thePublisher, kAppSignature,
  698.                                           thisDocument^.fileSpecPtr, eRefNum);
  699.     IF openErr <> noErr THEN
  700.     {If the open failed, then you can't write, }            
  701.     { so don't continue with this operation.}        
  702.     MyErrHandler(openErr);
  703.     {Get the text data to write. The GetTextInSection }
  704.     { function accomplishes this.}
  705.     textHandle := GetTextInSection(thePublisher, thisDocument);
  706.     {Write out text data.}
  707.     HLock(textHandle);
  708.     writeErr := WriteEdition(eRefNum, 'TEXT', textHandle^,
  709.                                        GetHandleSize(textHandle));
  710.     HUnLock(textHandle);
  711.     IF writeErr <> noErr THEN
  712.     BEGIN
  713.         {There were problems writing; simply close the edition. }
  714.         { When successful = FALSE, the edition data <> section }
  715.         { data. Note: this isn't fatal or bad; it just means }
  716.         { that the data wasn't written and no Section Read events }
  717.         { will be generated.}
  718.         closeErr := CloseEdition(eRefNum, FALSE);
  719.     END ELSE
  720.     BEGIN
  721.         {The write was successful; now close the edition. }
  722.         { When successful = TRUE, the edition data = section data.}                                                                                            
  723.         { This edition is now available to any subscibers. }
  724.         { Section Read events will be sent to current subscribers.}
  725.         closeErr := CloseEdition(eRefNum, TRUE);
  726.     END;
  727. END; {DoWriteEdition}
  728. Creating a Subscriber
  729. You need to create a Subscribe To menu command in the Edit menu. When a user chooses Subscribe To from this menu, your application should display the subscriber dialog box on the user’s screen. 
  730. Use the NewSubscriberDialog function to display the subscriber dialog box on the user’s screen. This function is similar to the CustomGetFile procedure described in the Standard File Package chapter in this volume.
  731. To create a subscriber, you must get information from the user, such as the name of the edition being subscribed to. The dialog box displays a listing of all available editions and allows the user to see a preview (thumbnail sketch) of the edition selected. Figure 1-12 shows a sample subscriber dialog box.
  732. A sample subscriber dialog box
  733. The subscriber dialog box allows the user to choose an edition to subscribe to. The NewSubscriberDialog function handles all user interaction until a user clicks Subscribe or Cancel. When a user selects an edition container, the Edition Manager accesses the preview for the edition container (if it is available) and displays it. 
  734. You pass a new subscriber reply record as a parameter to the NewSubscriberDialog function. 
  735. TYPE        NewSubscriberReply =
  736.         RECORD
  737.             canceled:                    Boolean;                    {user canceled dialog }
  738.                                                     { box}    
  739.             formatsMask:                    SignedByte;                    {formats required}
  740.             container:                    EditionContainerSpec;                            
  741.                                                     {edition selected}
  742.         END;
  743. The canceled field returns a Boolean value of TRUE if the user clicked Cancel. To indicate which edition format types (text, graphics, or sound) your application can read, you set the formatsMask field to one or more of these constants: 
  744. CONST        kPICTformatMask                        = 1;                    {Can subscribe to 'PICT', } 
  745.         kTEXTformatMask                        = 2;                    { 'TEXT', and }
  746.         ksndFormatMask                        = 4;                    { 'snd '.}
  747. To support a combination of formats, add the constants together. For example, a formatsMask of 3 displays both graphics and text edition format types in the subscriber dialog box. 
  748. The container field is of data type EditionContainerSpec. You must initialize the container field with the default edition volume reference number, directory ID, filename, and part. To do so, use the GetLastEditionContainerUsed function to obtain the name of the last edition displayed in the dialog box. 
  749. err := GetLastEditionContainerUsed (container);
  750. This function returns the last edition container for which a new subscriber was created using the NewSection function. If there is no last edition, or if the edition was deleted, GetLastEditionContainerUsed still returns the correct volume reference number and directory ID to use, but leaves the filename blank and returns the fnfErr result code. 
  751. The container field is of data type EditionContainerSpec.
  752. TYPE EditionContainerSpec = 
  753.     RECORD
  754.         theFile:                        FSSpec;                    {file containing edition }
  755.                                                     { data}
  756.         theFileScript:                        ScriptCode;                    {script code of filename}
  757.         thePart:                        LongInt;                    {which part of file, }
  758.                                                     { always kPartsNotUsed}
  759.         thePartName:                        Str31;                    {not used in version 7.0}
  760.         thePartScript:                        ScriptCode;                    {not used in version 7.0}
  761.     END;
  762. The field theFile is of type FSSpec. See the File Manager chapter in this volume for further information on file system specification records. 
  763. After filling in the fields of the new subscriber reply record, pass it as a parameter to the NewSubscriberDialog function, which displays the subscriber dialog box. 
  764. err := NewSubscriberDialog (reply);
  765. After displaying the subscriber dialog box, call the NewSection function to create the section record and the alias record. See “Creating the Section Record and Alias Record” earlier in this chapter for detailed information. 
  766. If the subscriber is set up to receive new editions automatically (not manually), the Edition Manager sends your application a Section Read event. Whenever your application receives a Section Read event, it should read the contents of the edition into the subscriber.
  767. Listing 1-6 illustrates how to create a subscriber. As described earlier, you must set up and display the subscriber dialog box to allow the user to subscribe to all available editions. After your application creates a subscriber, your application receives a Section Read event to read in the data being subscribed to. Be sure to add the newly created section to your list of sections for this file. There are many different techniques for creating subscribers and unique IDs; this listing displays one technique. 
  768. Creating a subscriber
  769. PROCEDURE DoNewSubscriber(thisDocument: MyDocumentInfoPtr);
  770.  
  771. VAR
  772.     getLastErr:                    OSErr;
  773.     dialogErr:                    OSErr;
  774.     sectionErr:                    OSErr;
  775.     resID:                    Integer;
  776.     thisSectionH:                    SectionHandle;
  777.     reply:                    NewSubscriberReply;
  778. BEGIN
  779.     {Put default edition name into reply record.}
  780.     getLastErr := GetLastEditionContainerUsed(reply.container);
  781.  
  782.     {Can subscribe to pictures or text.}
  783.     reply.formatsMask := kPICTformatsMask + kTEXTformatsMask;
  784.  
  785.     {Display dialog box and let user select.}
  786.     dialogErr := NewSubscriberDialog(reply);
  787.     {There's usually no error returned here, but if there is, }
  788.     { then it makes no sense to continue with this operation. }
  789.     { Pass control to MyErrHandler.}
  790.     IF dialogErr <> noErr THEN MyErrHandler(dialogErr);
  791.  
  792.     {Do nothing if user canceled.}
  793.     IF reply.canceled THEN EXIT(DoNewSubscriber);
  794.  
  795.     {Advance counter to make a new unique sectionID for this }
  796.     { document. It is not necessary to equate section IDs with }
  797.     { resources.}
  798.     thisDocument^.nextSectionID := thisDocument^.nextSectionID + 1;
  799.  
  800.     {Create a subscriber section.}
  801.     sectionErr := NewSection(reply.container,
  802.                                       thisDocument^.fileSpecPtr,
  803.                                      stSubscriber, 
  804.                                      thisDocument^.nextSectionID,
  805.                                       sumAutomatic, thisSectionH);
  806.     IF sectionErr <> noErr THEN
  807.     {Same reasoning as above. If a new section could not be }
  808.     { created, don't continue with this operation. Pass }
  809.     { control to MyErrHandler.}
  810.     MyErrHandler(sectionErr);
  811.  
  812.     resID := thisDocument^.nextSectionID;
  813.  
  814.     {Add this section/alias pair to your internal bookkeeping. }
  815.     { AddSectionAliasPair is a routine to accomplish this.}
  816.     AddSectionAliasPair(thisDocument, thisSectionH, resID);
  817.  
  818.     {Remember that you will receive a Section Read event to read }
  819.     { in the edition that you just subscribed to because the 
  820.     { initial mode is set to sumAutomatic.}
  821.  
  822.     {Remember that the section and alias records need to be saved } 
  823.     { as resources when the user saves the document.}
  824.  
  825. END; {DoNewSubscriber}
  826. Opening an Edition Container to Read Data
  827. Before reading data from an edition, you must use the OpenEdition function. Your application should only use this function for a subscriber. Use this function to initiate the reading of data from an edition.
  828. err := OpenEdition (subscriberSectionH, refNum);
  829. As a precaution, you should retain the old data until the user can no longer undo. This allows you to undo changes if the user requests it.
  830. Your application can supply a procedure such as DoReadEdition to read in data from the edition to a subscriber. When your application opens a document containing a subscriber that is set up to receive new editions automatically, the Edition Manager sends you a Section Read event if the edition has been updated. The Section Read event supplies the handle to the section that requires updating. Listing 1-7 provides an example of reading data from an edition.
  831. Choosing Which Edition Format to Read
  832. After your application opens the edition container for a subscriber, it can look in the edition for formats that it understands. To accomplish this, use the EditionHasFormat function.
  833. err := EditionHasFormat (whichEdition, whichFormat, formatSize);
  834. The EditionHasFormat function returns the noTypeErr result code if a requested format is not available. If the requested format is available, this function returns the noErr result code, and the formatSize parameter contains the size of the data in the specified format or kFormatLengthUnknown (–1), which signifies that the size is unknown.
  835. After your application opens the edition container and determines which formats it wants to read, call the ReadEdition function to read in the edition data. See “Reading and Writing Edition Data” earlier in this chapter for detailed information.
  836. After you have completed writing the edition data into the subscriber section, call the CloseEdition function to close the edition. See “Closing an Edition” earlier in this chapter for detailed information.
  837. Listing 1-7 illustrates how to read data from an edition. As described earlier, you must open the edition, determine which formats to read, use the ReadEdition function to read in data, and then use the CloseEdition function to close the edition. This listing shows how to read only text.
  838. Reading in edition data
  839. PROCEDURE DoReadEdition(theSubscriber: SectionHandle);
  840.  
  841. VAR
  842.     eRefNum:                        EditionRefNum;
  843.     openErr:                        OSErr;
  844.     readErr:                        OSErr;
  845.     closeErr:                        OSErr;
  846.     thisDocument:                        MyDocumentInfoPtr;
  847.     textHandle:                        Handle;
  848.     formatLen:                        Size;
  849.  
  850. BEGIN
  851.     {Find out which document this section belongs to. }
  852.     { The FindDocument function accomplishes this.}
  853.     thisDocument := FindDocument(theSubscriber);
  854.  
  855.     {Open the edition for reading.}
  856.     openErr := OpenEdition(theSubscriber, eRefNum);
  857.     IF openErr <> noErr THEN
  858.     {If the open failed, then most likely you can't read, }
  859.     { so don't continue with this operation.}
  860.         MyErrHandler(openErr);
  861.  
  862.     {Look for 'TEXT' format.}
  863.     IF EditionHasFormat(eRefNum, 'TEXT', formatLen) = noErr THEN
  864.     BEGIN
  865.         {Get the handle of location to read to. }
  866.         { The GetTextInSection function accomplishes this.}
  867.         textHandle := GetTextInSection(theSubscriber, thisDocument);
  868.         SetHandleSize(textHandle, formatLen);
  869.         HLock(textHandle);
  870.         readErr := ReadEdition(eRefNum, 'TEXT', textHandle^, 
  871.                                       formatLen);
  872.         HUnLock(textHandle);
  873.  
  874.         IF readErr = noErr THEN
  875.         BEGIN
  876.             {The read was successful; now close the edition. When}
  877.             { successful = TRUE, the section data = edition data.}
  878.             closeErr := CloseEdition(eRefNum, TRUE);
  879.             EXIT(DoReadEdition);
  880.         END;                                                
  881.     END;                            
  882.     {'TEXT' format wasn't found or read error; just close }
  883.     { the edition. FALSE tells the Edition Manager that your }
  884.     { application did not get the latest edition.}
  885.     closeErr := CloseEdition(eRefNum, FALSE);
  886.  
  887.     END; {DoReadEdition} 
  888. Using Publisher and Subscriber Options
  889. There are special options associated with publishers and subscribers within documents. Your application can use the publisher and subscriber options dialog boxes provided by the Edition Manager to make these choices available to the user. You should make these dialog boxes available to the user by creating a menu command in the Edit menu that toggles between Publisher Options (when the user has selected a publisher within a document) and Subscriber Options (when a user has selected a subscriber within a document). 
  890. When a user chooses these menu commands, you need to display the corresponding publisher or subscriber options dialog box. Use the SectionOptionsDialog function to display the appropriate dialog box on the user’s screen.
  891. err := SectionOptionsDialog (reply);
  892. Each dialog box contains information regarding the section and its edition. Figure 1-13 shows the publisher options dialog box with the update mode set to On Save. 
  893. The publisher options dialog box with update mode set to On Save
  894. Figure 1-14 shows the publisher options dialog box with the update mode set to Manually. 
  895. The publisher options dialog box with update mode set to Manually 
  896. As a shortcut for the user, you should display the publisher options dialog box when the user double-clicks on a publisher section within a document. Figure 1-15 shows the subscriber options dialog box with the update mode set to Automatically. 
  897. The subscriber options dialog box with update mode set to Automatically 
  898. Figure 1-16 shows the subscriber options dialog box with the update mode set to Manually.
  899. The subscriber options dialog box with update mode set to Manually
  900. As a shortcut for the user, you should display the subscriber options dialog box when the user double-clicks on a subscriber section within a document. 
  901. You pass a section options reply record as a parameter to the SectionOptionsDialog function. 
  902. TYPE SectionOptionsReply = 
  903.     RECORD
  904.         canceled:                Boolean;                        {user canceled dialog box}    
  905.         changed:                Boolean;                        {changed section record}    
  906.         sectionH:                SectionHandle;                         {handle to the specified }
  907.                                                 { section record}
  908.         action:                ResType;                        {action codes}    
  909.     END;
  910. Set the sectionH parameter to the handle to the section record for the section the user selected. 
  911. Upon return of the SectionOptionsDialog function, the canceled and changed fields are set. If the canceled parameter is set to TRUE, the user canceled the dialog box. Otherwise, this parameter is FALSE. If the changed parameter is TRUE, the section record is changed. For example, the user may have changed the update mode. 
  912. The action parameter contains the code for one of five user actions. All action codes dismiss the publisher and subscriber options dialog boxes when complete.
  913. n    action code is 'read' for user selection of the Get Edition Now button
  914. n    action code is 'writ' for user selection of the Send Edition Now button
  915. n    action code is 'goto' for user selection of the Open Publisher button
  916. n    action code is 'cncl' for user selection of the Cancel Publisher or Cancel Subscriber button
  917. n    action code is '      ' ($20202020) for user selection of the OK button 
  918. Listing 1-8 shows an example of how your application can respond to the action codes received from the section options reply record. There are several different techniques that your application can use to accomplish this—this listing shows one technique.
  919. Responding to action codes
  920. PROCEDURE DoOptionsDialog(theSection: SectionHandle);
  921.  
  922. VAR
  923.     reply:                        SectionOptionReply;
  924.     theEditionInfo:                        EditionInfoRecord;
  925.     action:                        ResType;
  926.     sodErr:                        OSErr;
  927.     geiErr:                        OSErr;
  928.     gpiErr:                        OSErr;
  929.  
  930. BEGIN
  931.     reply.sectionH := theSection;
  932.     sodErr := SectionOptionsDialog(reply);        
  933.     
  934.     {Determine what the user did and handle appropriately.}
  935.     IF reply.canceled THEN
  936.         {The user changed his/her mind; simply return.}
  937.         EXIT(DoOptionsDialog);
  938.  
  939.     IF reply.changed THEN
  940.         {The section record has changed; make note of this. }
  941.         { SectionHasChanged is a routine to accomplish this.}
  942.         SectionHasChanged(theSection);
  943.         {If you customize, you may want to do some }
  944.         { post-processing now.}
  945.  
  946.     action := reply.action;        {Get the action code.}
  947.  
  948.     IF (action = 'read') THEN
  949.     BEGIN    {User selected Get Edition Now button.}
  950.         DoReadEdition(theSection);
  951.         EXIT(DoOptionsDialog);
  952.     END;
  953.     IF (action = 'writ') THEN
  954.     BEGIN    {User selected Send Edition Now button.}
  955.         DoWriteEdition(theSection);
  956.         EXIT(DoOptionsDialog);
  957.     END;
  958.  
  959.     IF (action = 'goto') THEN
  960.     BEGIN    {User selected Open Publisher button.}
  961.         geiErr := GetEditionInfo(theSection, theEditionInfo);                    
  962.         {There's usually no error returned here, but if }                        
  963.         { there is,             then don't continue with this operation.}        
  964.         IF geiErr <> noErr THEN MyErrHandler(geiErr);
  965.  
  966.         gpsErr := GotoPublisherSection(theEditionInfo.container);
  967.         {Same comment as above. Pass control to MyErrHandler }                
  968.         { if there's an error.}                                    
  969.         IF gpsErr <> noErr THEN MyErrHandler(gpsErr);
  970.         EXIT(DoOptionsDialog);
  971.     END;
  972.  
  973.     IF (action = 'cncl') THEN
  974.     BEGIN     {User selected Cancel Publisher or Cancel }
  975.         { Subscriber button.Call the UnRegisterSection }
  976.         { function and dispose of the section record and }
  977.         { the alias record.}
  978.         EXIT(DoOptionsDialog);
  979.     END;
  980. END; {DoOptionsDialog}
  981. The following sections describe the features of the publisher and subscriber options dialog boxes.
  982. Publishing a New Edition While Saving or Manually
  983. By default, your application should write publisher data to an edition each time the user saves the document and the contents of the publisher differ from the latest edition. In the publisher options dialog box, the user can choose to write new data to an edition each time the document is saved (by clicking On Save) or only when the user specifically requests it (by clicking Manually). 
  984. When the update mode is set to manual, a user must click the Send Edition Now button within the publisher options dialog box to write publisher data to an edition. When a user clicks Send Edition Now, the section options reply record contains the action code 'writ'. Write out the new edition beginning with the OpenNewEdition function. Writing to an edition manually is useful when a user tends to save a document numerous times while revising it.
  985. Each time the user saves the document, check the update mode of the publisher section. If the publisher section sends its data to an edition on save, check to see whether the publisher data has changed since it was last written out to the edition. If so, write out the new edition. 
  986. In addition, you may also support a Stop All Editions menu command to provide a method for temporarily suspending all update activity. See “Publishers, Subscribers, and Editions” earlier in this chapter for additional information. 
  987. Subscribing to an Edition Automatically or Manually
  988. By default, your application should subscribe to an edition each time new edition data becomes available. In the subscriber options dialog box, the user can choose to read new data from an edition as the data is available (by clicking Automatically) or only when the user specifically requests it (by clicking Manually). 
  989. When the update mode is set to manual, the user must click the Get Edition Now button within the subscriber options dialog box to receive new editions. When a user clicks this button, the section options reply record contains the action code 'read'. Read in the new edition beginning with the OpenEdition function. See “Opening an Edition Container to Read Data” earlier in this chapter for detailed information.
  990. When the update mode is set to automatic, your application receives a Section Read event each time a new edition becomes available. In response, you should read the new edition data beginning with the OpenNewEdition function.
  991. Your application does not receive Section Read events for subscribers that receive new editions manually.
  992. You may also support a Stop All Editions menu command to provide a method for temporarily suspending all update activity. See “Publishers, Subscribers, and Editions” earlier in this chapter for additional information. 
  993. Canceling Sections Within Documents
  994. The option of canceling publishers and subscribers is available to the user through the Cancel Publisher and Cancel Subscriber buttons in the corresponding options dialog boxes. When the user wants to cancel the publisher or cancel the subscriber within a document, the action code of the section options reply record is 'cncl'. See “Relocating an Edition” later in this chapter for additional information on canceling a section. 
  995. When a user cancels a section (either a publisher or subscriber) and then saves the document, or when a user closes an untitled document (which contains newly created sections) without saving, you must unregister each corresponding section record and alias record using the UnRegisterSection function. In addition, you should also delete the section record and alias record using the DisposHandle procedure. See the Memory Manager chapter in Volume I for additional information on the DisposHandle procedure. When a user cancels a publisher section and then saves the document, or when a user closes an untitled document (which contains newly created publishers) without saving, you must also delete any corresponding edition containers (in addition to deleting section records and alias records).
  996. Do not delete an edition container file, section record, or alias record until the user saves the document—the user may decide to undo changes before saving the document. 
  997. To locate the appropriate edition container to be deleted (before you use the UnRegisterSection function), use the GetEditionInfo function. 
  998. err := GetEditionInfo (sectionH, editionInfo);
  999. The editionInfo parameter is a record of data type EditionInfoRecord.
  1000. TYPE EditionInfoRecord = 
  1001.     RECORD
  1002.         crDate:                TimeStamp;                            {date edition container }
  1003.                                                     { was created}
  1004.         mdDate:                TimeStamp;                            {date of last change}
  1005.         fdCreator:                OSType;                            {file creator}
  1006.         fdType:                OSType;                            {file type}
  1007.         container:                EditionContainerSpec;                            {the edition}
  1008.     END;
  1009. The GetEditionInfo function returns the edition container as part of the edition information. 
  1010. The crDate field contains the creation date of the edition. The mdDate field contains the modification date of the edition. 
  1011. The fdType and the fdCreator fields are the type and creator of the edition file. The container field includes a volume reference number, directory ID, filename, script, and part number for the edition. 
  1012. To remove the edition container, use the DeleteEditionContainerFile function. 
  1013. err := DeleteEditionContainerFile (editionFile);
  1014. Locating a Publisher Through a Subscriber
  1015. The user can locate a publisher from a subscriber within a document by clicking the Open Publisher button in the subscriber options dialog box. As a shortcut, Apple suggests that you also allow the user to locate a publisher when the user selects a subscriber within a document and presses Option–double-click. 
  1016. When the action code of the SectionOptionsReply record is 'goto', use the GoToPublisherSection function. 
  1017. err := GoToPublisherSection (container);
  1018. The GoToPublisherSection function locates the correct document by resolving the alias in the edition, and it launches the document’s application if necessary (the Edition Manager sends an Open Documents event). The Edition Manager then sends the publishing application a Section Scroll event. If the document containing the requested publisher is located on the same computer as its subscriber, the document opens and scrolls to the location of the publisher. If the document containing the requested publisher is located on a shared volume (using file sharing), the document opens and scrolls to the location of the publisher only if the user has privileges to open the document from the Finder.
  1019. You need to provide the GoToPublisherSection function with the edition container. To accomplish this, use the GetEditionInfo function. See the previous section, “Canceling Sections Within Documents,” for information on the GetEditionInfo function. 
  1020. Renaming a Document Containing Sections
  1021. If a user renames a document that contains sections by choosing Save As from the File menu, or if a user pastes a portion of a document that contains a section into another document, use the AssociateSection function.
  1022. Use the AssociateSection function to update the alias record of a registered section. 
  1023. err := AssociateSection (sectionH, newSectionDocument);
  1024. The AssociateSection function internally calls the UpdateAlias function. It is also possible to update the alias record using the Alias Manager (see the Alias Manager chapter in this volume for additional information). 
  1025. Displaying Publisher and Subscriber Borders
  1026. Each publisher and subscriber within a document should have a border that appears when a user selects the contents of these sections. You should display a publisher border as 3 pixels wide with 50 percent gray lines and a subscriber border as 3 pixels wide with 75 percent gray lines. Separate the contents of the section from the border itself with one pixel of white space. To create your borders, you should use patterns—not colors. Depending on the user’s monitor type, colors may not be distinguishable. 
  1027. In general, borders for publishers and subscribers should behave like the borders of 'PICT' graphics within a word-processing document. A border should appear when the user clicks within the content area of a publisher or a subscriber and disappear when the user clicks outside the content area of a section. You can also make all publisher and subscriber borders appear or disappear by implementing an optional Show/Hide Borders menu command. Figure 1-17 displays the Edition Manager Show/Hide Borders menu command in the Edit menu. 
  1028. Edit menu with Show/Hide Borders menu command
  1029. Depending on your application, you may choose to include resize handles or similar components in your borders. See “Object-Oriented Graphics Borders” later in this chapter for an example of resize handles.
  1030. Whenever a user selects a portion of a publisher or inserts a cursor into the publisher, you should display the border as 50 percent gray. A user can copy the contents of a publisher or subscriber without copying the section itself by selecting the data, copying, and then pasting the data in a new location. A user can cut and paste a selection that contains an entire publisher or subscriber, but you should discourage users from making multiple copies of a publisher. See “Duplicating Publishers and Subscribers” later in this chapter for detailed information.
  1031. When the user modifies a publisher, your application should grow or shrink its border to accommodate the new dimension of the section.
  1032. You should display only one publisher border within a document at a time. If a cursor is inserted within a publisher that is contained within a larger publisher, you should display only the smaller, internal publisher border. If it is absolutely necessary to display all section borders within a document at the same time, you can create a Show/Hide Borders menu item. 
  1033. You do not need to provide support for publishers contained within other publishers. If you do not, you should dim the Create Publisher menu command (to indicate that it is not selectable) when a user attempts to create a publisher within an existing publisher.
  1034. Figure 1-18 shows the recommended border behavior for publishers when borders are shown, when a user selects the contents of a section, and when a user selects data within a document that includes a publisher section. 
  1035. Publisher borders
  1036. Figure 1-19 shows the recommended border behavior for subscribers when borders are shown, when a user selects the contents of a section, and when a user selects data within a document that includes a subscriber section.
  1037. Subscriber borders
  1038. If a user tries to select only a portion of a subscriber, you should highlight the entire contents of the subscriber. A user cannot edit the data contained within a subscriber. See “Modifying a Subscriber” later in this chapter for detailed information.
  1039. If a user cancels a section using the publisher or subscriber options dialog box, your application should leave the contents of the section within the document, but you should be sure to remove the borders from this data, as it is no longer considered a section.
  1040. Generally, the appearance and function of publisher and subscriber borders should be the same across different applications. See the following sections entitled “Text Borders,” “Spreadsheet Borders,” “Object-Oriented Graphics Borders,” and “Bitmapped Graphics Borders” for descriptions of specialized features for publisher and subscriber borders in word processing, spreadsheet, or graphics applications. 
  1041. Text Borders
  1042. In word-processing documents, a publisher may contain other publishers. However, one publisher should not overlap another publisher. You should display only one publisher border at a time. If an insertion point is placed within a publisher that is encompassed by another larger publisher, you should display only the smaller internal publisher border. 
  1043. In exceptional cases, it may be necessary to display more than one publisher or subscriber border at a time. For example, a publisher may consist of a paragraph that includes a marker for a footnote. The data contained within the footnote should also be considered part of the publisher. When a user selects the paragraph, you should simultaneously display a border around the footnote.
  1044. The border of a publisher that contains text should be located between characters within the text. The insertion point, when placed on such a boundary, should gravitate toward the publisher. That is, a click in front (to the left) of a publisher border should place the cursor inside the publisher, so that subsequent typing goes inside the publisher. Clicking at the end (to the right) of a publisher border should also place the cursor inside the publisher.
  1045. Whenever two separate borders are adjacent to one another (side by side), the boundary click should go in between them. This is also true for a border that is next to other nontextual aspects of a document, such as 'PICT' graphics or page breaks.
  1046. When a user removes information from a publisher that contains text data, the border should become smaller to accommodate the new text. When a user adds information to the publisher, the border should grow to show the enlarged area of the publisher. The insertion point should remain within the publisher. 
  1047. If a user highlights the entire contents of a publisher and then chooses Cut from the Edit menu, you should not delete the publisher border within the document. The user may intend to delete the existing publisher data and replace it with new data, or the user may want to move the entire publisher and its data to a new location. Figure 1-20 shows this state. 
  1048. A publisher with contents removed
  1049. You should leave the cursor inside the small publisher border for further typing. If the user inserts the cursor in a new location (instead of typing data inside the existing border), you need to remove the empty publisher border from the document to allow the user to move the publisher. This effectively deletes the publisher from the document. If the user pastes the publisher that is currently held in the Clipboard, you should recreate its border. If the user cuts or copies other data from the document before pasting the publisher from the Clipboard, the publisher should be removed from the Clipboard. 
  1050. Spreadsheet Borders
  1051. Borders around spreadsheet data or other data in arrays should look and behave very much like text borders. Figure 1-21 shows a typical border within a spreadsheet document.
  1052.   A publisher border within a spreadsheet document
  1053. Note that the border goes below the column headers (A, B, C, D) and to the right of the row labels (1, 2, 3, 4)—it should not overlap these cell boundaries. The border at the bottom and the border on the right side can be placed within the adjacent cells (outside of the cells that constitute the publisher).
  1054. In contrast to word-processing applications, borders in spreadsheet documents (or other documents with array data) can overlap. That is, a user can select a row of cells to be a publisher and an overlapping column of those cells to be another publisher. You should never display more than one publisher border at a time. When a user selects a spreadsheet cell that is part of more than one publisher, you should display only the border of the publisher that was last edited. (This can be accomplished by comparing the modification dates of the publishers.)
  1055. If it is absolutely necessary to display all section borders within a document at the same time, you can create a Show/Hide Borders command in the Edit menu to toggle all borders on and off. 
  1056. When data is added to or deleted from a publisher that consists of a spreadsheet cell or other array, its border should grow or shrink to accommodate the addition or deletion of data. A publisher should behave like a named range in a spreadsheet. For example, if a user cuts a row within a publisher that consists of a named range in a spreadsheet, you should shrink the publisher data and its border correspondingly.
  1057. When a user cuts a publisher and its entire contents within a spreadsheet document, the entire section should be held in the Clipboard. Do not leave an empty publisher border in a spreadsheet (as recommended for text borders). If a user attempts to paste a copy of an existing publisher, you should warn the user by displaying an alert box (see “Duplicating Publishers and Subscribers” later in this chapter).
  1058. Object-Oriented Graphics Borders
  1059. In an object-oriented drawing application, the publisher border should fit just around the selected objects.
  1060. You can provide resize handles that appear with all drawing objects to allow the user to resize the border of a publisher. Figure 1-22 shows a publisher border with resize handles.
  1061. A publisher border with resize handles
  1062. A user can create freeform graphics within drawing applications that cause publisher borders to seemingly float over the area the user publishes. The border acts like a clipping rectangle—anything within the border becomes the publisher. Figure 1-23 shows a publisher that contains clipped graphics and its subscriber in another application.
  1063. A user can create publishers and subscribers that overlap each other. Thus, borders may overlap and it may no longer be possible to turn on a particular border when the user clicks within a publisher. Drawing applications should provide a menu command, Show Borders, that toggles to Hide Borders. This command should allow users to turn all publisher and subscriber borders on or off.
  1064.  A publisher and subscriber with clipped graphics
  1065. Bitmapped Graphics Borders
  1066. Creating a border around bitmapped graphics in applications is similar to doing so in object-oriented drawing applications. The border appears around the selected area. The user can create overlapping publishers and subscribers in bitmapped graphics applications. You need to provide a Show/Hide Borders command to allow users to turn all borders on and off.
  1067. Duplicating Publishers and Subscribers
  1068. Whenever a user clicks a publisher or subscriber border, you should change the contents of the section to a selected state. You should discourage users from making multiple copies of a publisher and pasting them in the same or other documents, because the contents of the edition would be difficult or impossible to predict. Multiple copies of the same publisher also contain the same control block value. See “Creating and Registering a Section” later in this chapter for detailed information on control blocks. 
  1069. When a user attempts to create a copy of a publisher that already exists, you should display an alert box such as the one shown in Figure 1-24. 
  1070. Creating multiple publishers alert box
  1071. When a user attempts to save a document that contains multiple copies of the same publisher, display an alert box such as the one shown in Figure 1-25.
  1072. Saving multiple publishers alert box
  1073. If a user decides to ignore your alert box, your application should still save the document, but you should continue to display this error message every time the user saves this document. 
  1074. A user can modify the contents of any duplicate publisher, but the contents of the edition will be whichever publisher was the last to write.
  1075. When a user chooses to copy and paste or duplicate a section, use the HandToHand function (described in the Operating System Utilities chapter in Volume II) to duplicate the section record and alias record. Put the alias field of the cloned section record with the handle to the cloned alias record and generate a unique section identification number for it. In addition, you should also place the section data, section record, and alias record in the scrap.
  1076. Use the RegisterSection function (described earlier in “Opening and Closing a Document Containing Sections”) to register the cloned section’s section record.
  1077. A user can select the contents of a publisher without selecting the border and copy just the data to a new location. In this case, the user has simply copied data (and not the publisher). Do not create a border for this data in the new location.
  1078. Modifying a Subscriber
  1079. When the user selects data or clicks in the data area of a subscriber, you should highlight the entire contents of the subscriber using reverse video. You can allow users to globally adorn subscribers. For example, a user might select a subscriber within a document and change all text from plain to bold. However, you should discourage users from modifying the individual elements contained within a subscriber—for example, by editing a sentence or rotating an individual graphical object. 
  1080. Remember that each time a new edition arrives for a subscriber, any modifications that the user has introduced are overwritten. Global adornment of a subscriber is much easier for your application to regenerate.
  1081. If you do allow a user to edit a subscriber section, provide an enable/disable editing option within the subscriber options dialog box using the SectionOptionsExpDialog function, described later in “Customizing Dialog Boxes.” When you allow a user to edit a subscriber, you should change the subscriber from a selected state to editable data. 
  1082. In addition to global adornment, your application may also need to support partial selection of subscribers to enable spell checking and search operations.
  1083. Because a user can modify a publisher just like any other portion of a document, its subscriber may change in size as well as content. For example, a user may modify a publisher by adding two additional columns to a spreadsheet. 
  1084. Relocating an Edition
  1085. In the Finder, users cannot move an edition across volumes. To relocate an edition, the user must first select its publisher and cancel the section (remember to remove the border). The user needs to republish and then select a new volume location for the edition. As a convenience for the user, you should retain the selection of all the publisher data after the user cancels the section to make it easy to republish the section. 
  1086. Customizing Dialog Boxes
  1087. The expandable dialog box functions allow you to add items to the bottom of the dialog boxes, apply alternate mapping of events to item hits, apply alternate meanings to the item hits, and choose the location of the dialog boxes. See the Dialog Manager chapter in Volume I and the Standard File Package chapters in Volumes I and VI for additional information. 
  1088. The expandable versions of these dialog boxes require five additional parameters. Use the NewPublisherExpDialog function to expand the publisher dialog box.
  1089. err := NewPublisherExpDialog (reply, where, expansionDITLresID, 
  1090.                                         dlgHook, filterProc, yourDataPtr);
  1091. Use the NewSubscriberExpDialog function to expand the subscriber dialog box.
  1092. err := NewSubscriberExpDialog (reply, where, expansionDITLresID,
  1093.                                          dlgHook, filterProc, yourDataPtr);
  1094. Use the SectionOptionsExpDialog function to expand the publisher options and the subscriber options dialog boxes. 
  1095. err := SectionOptionsExpDialog (reply, where, expansionDITLresID,
  1096.                                           dlgHook, filterProc, yourDataPtr);
  1097. The reply parameter is a pointer to a NewPublisherReply, NewSubscriberReply, or SectionOptionsReply record, respectively.
  1098. You can automatically center the dialog box by passing (–1, –1) in the where parameter. 
  1099. The expansionDITLresID parameter should be 0 or a valid dialog item list ('DITL') resource ID. This integer is the ID of a dialog item list whose items are appended to the end of the standard dialog item list. The dialog items keep their relative positions, but they are moved as a group to the bottom of the dialog box. See the Dialog Manager chapter in Volume I for additional information on dialog item lists.
  1100. The filterProc parameter should be a valid, expandable modal filter procedure pointer or NIL. This procedure is called by the ModalDialog function. The filterProc function enables you to map real events (such as a mouse-down event) to an item hit (such as clicking the Cancel button). For instance, you may want to map a keyboard equivalent to an item hit. See the Dialog Manager chapter in Volume I for information on the ModalDialog function.
  1101. The dlgHook parameter should be a valid, expandable dialog hook procedure pointer or NIL. This procedure is called after each call to the ModalDialog filter function. The dlgHook parameter takes the appropriate action, such as filling in a check box. The itemOffset parameter to the procedure is the number of items in the dialog item list before the expansion dialog items. You need to subtract the item offset from the item hit to get the relative item number in the expansion dialog item list. The return value from the dlgHook parameter is the absolute item number. 
  1102. When the Edition Manager displays subsidiary dialog boxes in front of another dialog box on the user’s screen, your dlgHook and filterProc parameters should check the refCon field in the WindowRecord data type (from the window field in the DialogRecord) to determine which window is currently in the foreground. The main dialog box for the NewPublisherExpDialog and the NewSubscriberExpDialog functions contains the following constant:
  1103. CONST            sfMainDialogRefCon                            = 'stdf';                {new publisher and }
  1104.                                                         { new subscriber}
  1105. The main dialog box for the SectionOptionsExpDialog function contains the following constant:
  1106. CONST            emOptionsDialogRefCon                                = 'optn';                {options dialog}
  1107. See “Summary of the Edition Manager” later in this chapter for additional constants. 
  1108. The yourDataPtr parameter is reserved for your use. It is passed back to your hook and modal filter procedure. This parameter does not have to be of type Ptr—it can be any 32-bit quantity that you want. In Pascal, you can pass in register A6 for yourDataPtr, and make dlgHook and filterProc local functions without the last parameter. The stack frame is set up properly for these functions to access their parent local variables. See the Standard File Package chapter in this volume for detailed information. 
  1109. For the NewPublisherExpDialog and NewSubscriberExpDialog functions, all the pseudo-items for the Standard File Package—such as sfHookFirstCall(–1), sfHookNullEvent(100), sfHookRebuildList(101), and sfHookLastCall(–2)—can be used, as well as emHookRedrawPreview(150).
  1110. For the SectionOptionsExpDialog function, the only valid pseudo-items are sfHookFirstCall(–1), sfHookNullEvent(100), sfHookLastCall(–2), emHookRedrawPreview(150), emHookCancelSection(160), emHookGoToPublisher(161), emHookGetEditionNow(162), emHookSendEditionNow(162), emHookManualUpdateMode(163), and emHookAutoUpdateMode(164). See the Standard File Package chapter in this volume for information on pseudo-items. 
  1111. 1The Edition Manager
  1112. Subscribing To Non-Edition Files
  1113. Using the Edition Manager, a subscriber can read data directly from another document, such as an entire 'PICT' file, instead of subscribing to an edition. This feature is for advanced applications that can set up bottleneck procedures for reading. Figure 1-26 shows a document that is subscribing directly to a 'PICT' file. 
  1114. For each application, the Edition Manager keeps a pointer to a bottleneck function. The Edition Manager never opens or closes an edition container directly. Instead, the Edition Manager calls the current edition opener. The InitEditionPack function (described later in “Initializing the Edition Manager”) sets up the current system opener function. 
  1115. To override the standard opener function, create an opener function that contains the following parameters. 
  1116. FUNCTION MyOpener (selector: EditionOpenerVerb; 
  1117.                          VAR PB: EditionOpenerParamBlock) : OSErr;
  1118. Subscribing directly to a 'PICT' file
  1119. Your opener needs to know which formats the file contains and how the data is supposed to be read or written. 
  1120. The opener can allocate a handle or pointer to contain information such as file reference numbers. This value is passed as ioRefNum to the I/O procedures. 
  1121. The eoOpen and eoOpenNew edition opener verbs (described later in “Calling an Edition Opener Procedure”) return a pointer to a function to do the actual reading and writing.
  1122. The following sections describe
  1123. n    how to get the current edition opener procedure
  1124. n    how to set your own edition opener procedure
  1125. n    how to call an edition opener procedure
  1126. n    the edition opener parameters
  1127. Getting the Current Edition Opener
  1128. When you want to get the current edition opener procedure, use the GetEditionOpenerProc function. 
  1129. err := GetEditionOpenerProc (opener);
  1130. The opener parameter returns the pointer to the current edition opener procedure. A different current opener is kept for each application. One application’s opener is never called by another application.
  1131. Setting an Edition Opener
  1132. You can provide your own edition opener procedure. To do so, use the SetEditionOpenerProc function. 
  1133. err := SetEditionOpenerProc (@MyOpener);
  1134. The @MyOpener parameter is a pointer to the edition opener procedure that you are providing. If you set the current opener to be a routine in your own code, be sure to call the GetEditionOpenerProc function first so that you can save the previous opener. If your opener is passed a selector that it does not understand, use the previous opener provided by the Edition Manager to handle it. See the next section for a list of selectors. 
  1135. Calling an Edition Opener Procedure
  1136. You use the CallEditionOpenerProc function to call an edition opener procedure. Since the Edition Manager is a package that may move, a real pointer cannot be safely returned for the standard opener and I/O procedures. The system opener and the I/O routines are returned as a value that is not a valid address to a procedure. The CallEditionOpenerProc and CallFormatIOProc functions check for these values and call the system procedures. 
  1137. You should never assume that a value for a system procedure is a fixed constant. 
  1138. err := CallEditionOpenerProc (selector, PB, routine);
  1139. Set the selector parameter to one of the edition opener verbs. The edition opener verbs include 
  1140. n    eoCanSubscribe
  1141. n    eoOpen
  1142. n    eoClose
  1143. n    eoOpenNew
  1144. n    eoCloseNew
  1145. The PB parameter of the CallEditionOpenerProc function is an edition opener parameter block. 
  1146. TYPE EditionOpenerParamBlock = 
  1147.     RECORD
  1148.         info:                    EditionInfoRecord;                            {edition container to }
  1149.                                                         { be subscribed to}
  1150.         sectionH:                    SectionHandle;                            {publisher or }
  1151.                                                         { subscriber }
  1152.                                                         { requesting open}
  1153.         document:                    FSSpecPtr;                            {document passed}
  1154.         fdCreator:                    OSType;                            {Finder creator type}
  1155.         ioRefNum:                    LongInt;                            {reference number}
  1156.         ioProc:                    FormatIOProcPtr;                            {routine to read }
  1157.                                                         { formats}
  1158.         success:                    Boolean;                            {reading or writing }
  1159.                                                         { was successful}
  1160.         formatsMask:                    SignedByte;                            {formats required to }
  1161.                                                         { subscribe}
  1162.     END;
  1163. The routine parameter of the CallEditionOpenerProc function is a pointer to an edition opener procedure.
  1164. The following list shows which fields of the edition opener parameter block are used by the edition opener verbs.
  1165. Opener 
  1166. verb        Field    Description    Called by
  1167. eoCanSubscribe    Æ     info    Edition container to subscribe to    NewSubscriberDialog
  1168.     Æ     formatsMask    Formats required to subscribe.    function for a 
  1169.     ¨    Return value    A noErr code indicates that an     subscriber
  1170.             edition container can be     
  1171.             subscribed to. A noTypeErr code
  1172.             indicates that an edition 
  1173.             container cannot be subscribed to.
  1174. eoOpen    Æ     info    Edition container to open for reading.    OpenEdition and
  1175.     Æ    sectionH    Subscriber section requesting     GetStandardFormats
  1176.             open or NIL.    functions for a 
  1177.     ¨     ioRefNum    Reference number for use by I/O     subscriber
  1178.             routine. Not the same as EditionRefNum.
  1179.     ¨     ioProc    I/O routine to call to read formats.
  1180.     ¨    Return value    A noErr code or appropriate error code.
  1181. eoClose    Æ     info    Edition container to be closed for    CloseEdition and
  1182.             reading.    GetStandardFormats
  1183.     Æ     sectionH    Subscriber section requesting close     functions for a
  1184.             or NIL.    subscriber
  1185.     Æ     ioRefNum    Value returned by eoOpen.
  1186.     Æ     ioProc    Value returned by eoOpen.
  1187.     Æ     success    Success value passed to the 
  1188.             CloseEdition function.
  1189.     ¨    Return value    A noErr code or appropriate error code.
  1190. eoOpenNew    Æ     info    Edition container to open for writing.    OpenNewEdition
  1191.     Æ     sectionH    Publisher section requesting     function for a
  1192.             open or NIL.    publisher
  1193.     Æ     document    Document pointer passed into the 
  1194.             OpenNewEdition function.
  1195.     Æ     fdCreator    The fdCreator passed into the 
  1196.             OpenNewEdition function.
  1197.     ¨     ioRefNum    Reference number for use by I/O 
  1198.             routine. Not the same as 
  1199.             EditionRefNum.
  1200.     ¨     ioProc    I/O routine to call to write formats.
  1201.     ¨    Return value    A noErr code or appropriate error code.
  1202. eoCloseNew    Æ     info    Edition container to be closed after     CloseEdition function
  1203.             writing.    for a publisher
  1204.     Æ     sectionH    Publisher section requesting close 
  1205.             or NIL.
  1206.     Æ     ioRefNum    Value returned by eoOpenNew.
  1207.     Æ     ioProc    Value returned by eoOpenNew.
  1208.     Æ     success    Success value passed to the 
  1209.             CloseEdition function.
  1210.     ¨    Return value    A noErr code or appropriate error code.
  1211. The sample code in Listing 1-9 demonstrates how to install your own edition opener function.
  1212. Using your own edition opener function
  1213. VAR
  1214.     gOriginalOpener: EditionOpenerProcPtr;    {global variable}
  1215.  
  1216. {Install your edition opener by saving off current opener }
  1217. { and then set the opener to point to your opener.}
  1218.  
  1219. PROCEDURE InstallMyOpener;
  1220. BEGIN
  1221.     FailOSErr(GetEditionOpenerProc(gOriginalOpener));
  1222.     FailOSErr(SetEditionOpenerProc(@MyEditionOpener));
  1223. END; {InstallMyOpener}
  1224.  
  1225. {This opener calls the original edition opener if it is passed }
  1226. { a selector verb it does not understand.}
  1227.  
  1228. FUNCTION MyEditionOpener (selector: EditionOpenerVerb; 
  1229.                                   VAR PB: EditionOpenerParamBlock) : 
  1230.                                     OSErr; 
  1231. BEGIN
  1232.     WITH PB DO
  1233.     BEGIN
  1234.         CASE selector OF
  1235.             eoCanSubscribe:
  1236.                 MyEditionOpener := MyCanSubscribe(PB);
  1237.             eoOpen:
  1238.                 MyEditionOpener := MyEditionOpen(PB);
  1239.             eoClose:
  1240.                 MyEditionOpener := MyEditionClose(PB);
  1241.             OTHERWISE
  1242.                 MyEditionOpener := CallEditionOpenerProc
  1243.                             (selector, PB, gOriginalOpener);
  1244.         END; {case}
  1245.     END; {with}
  1246. END; {MyEditionOpener}
  1247.  
  1248. {This function returns noErr if it can subscribe to the request }
  1249. { file. It is called by the Edition Manager to build the list of }
  1250. { files in NewSubscriberDialog. Notice that it calls the }
  1251. { original opener for files it does not understand.}
  1252.  
  1253. FUNCTION MyCanSubscribe (VAR PB: EditionOpenerParamBlock) : OSErr;
  1254. BEGIN
  1255.     {Check file type to see if it is a file you can emulate as an }
  1256.     { edition.}
  1257.     IF PB.info.fdType = {for example}'PICT' 
  1258.         THEN MyCanSubscribe := noErr
  1259.         {Otherwise, let the saved off edition opener decide.}
  1260.         ELSE MyCanSubscribe := CallEditionOpenerProc(eoCanSubscribe,
  1261.                                                                 PB, gOriginalOpener);
  1262. END; {MyCanSubscribe}
  1263. Opening and Closing Editions
  1264. Each time the Edition Manager opens or closes an edition container, it calls the current edition opener procedure and passes it an opener verb and a parameter block. 
  1265. Your opener must be careful when closing documents since a document may already have been opened by another application. Be sure to use the Open/Deny modes whenever possible. Do not close a document if it was already open when your application opened it.
  1266. Listing Files That Can Be Subscribed To
  1267. The NewSubscriberDialog function calls the eoCanSubscribe opener verb to build the list of files that can be subscribed to. The preview in the subscriber dialog box is generated by calling the GetStandardFormats function (described in “Edition Container Formats” later in this chapter), which calls the format I/O verbs eoOpen, ioHasFormat, ioRead, and then eoClose. See “Calling a Format I/O Procedure” later in this chapter for detailed information on format I/O verbs.
  1268. Reading From and Writing to Files
  1269. The I/O procedure is a routine that actually reads and writes the data. It too has an interface of a selector and a parameter block.
  1270. To override the standard reading and writing functions, create an I/O function. Note that you also need to provide your own opener function to call your I/O function. See “Calling an Edition Opener Procedure” earlier in this chapter.
  1271. FUNCTION MyIO (selector: FormatIOVerb; 
  1272.                     VAR PB: FormatIOParamBlock) :                 OSErr;
  1273. Calling a Format I/O Procedure
  1274. To indicate to the Edition Manager which format I/O procedure to use, use the CallFormatIOProc function.  
  1275. err := CallFormatIOProc (selector, PB, routine);
  1276. Set the selector parameter to one of the format I/O verbs. The format I/O verbs include 
  1277. n    ioHasFormat
  1278. n    ioReadFormat
  1279. n    ioNewFormat
  1280. n    ioWriteFormat
  1281. The PB parameter of the CallFormatIOProc function contains a format I/O parameter block. 
  1282. TYPE FormatIOParamBlock = 
  1283.     RECORD
  1284.         ioRefNum:                    LongInt;                    {reference number}
  1285.         format:                    FormatType;                    {edition format type}
  1286.         formatIndex    :                LongInt;                    {opener-specific enumeration }
  1287.                                                 { of formats}    
  1288.         offset:                    LongInt;                    {offset into format}
  1289.         buffPtr:                    Ptr;                    {data starts here}
  1290.         buffLen:                    LongInt;                    {length of data}
  1291.     END;
  1292. The routine parameter of the CallFormatIOProc function is a pointer to a format I/O procedure.
  1293. The following list shows which fields of FormatIOParamBlock are used by the format I/O verbs.
  1294. Opener 
  1295. verb        Parameter    Description    Called by
  1296. ioHasFormat    Æ     ioRefNum    I/O reference number returned     EditionHasFormat,
  1297.             by opener.    GetStandardFormats,
  1298.     Æ     format    Check for this format.    and ReadEdition
  1299.     ¨    formatIndex    An optional enumeration of the     functions
  1300.             supplied format.
  1301.     ¨    buffLen    If found, return the length size or –1 
  1302.             if size is unknown.
  1303.     ¨    Return value    A noErr or noTypeErr code.
  1304. ioReadFormat    Æ     ioRefNum    I/O reference number returned by     ReadEdition and
  1305.             opener.    GetStandardFormats
  1306.     Æ    format    Get this format.    functions
  1307.     Æ     formatIndex    Value returned by ioHasFormat.
  1308.     Æ     offset    Read format beginning from this offset.
  1309.     Æ     buffPtr    Put data beginning here.
  1310.     ´     buffLen    Specify buffer length to read, and return 
  1311.             actual amount received.
  1312.     ¨    Return value    A noErr code, or appropriate error code.
  1313. ioNewFormat    Æ     ioRefNum    I/O reference number returned by     SetEditionFormatMark
  1314.             opener.    and WriteEdition
  1315.     Æ     format    Create this format.    functions
  1316.     ¨    formatIndex    An optional enumeration of the 
  1317.             supplied format.
  1318.     ¨    Return value    A noErr code, or appropriate error code.
  1319. ioWriteFormat    Æ     ioRefNum    I/O reference number returned by     WriteEdition function
  1320.             opener.
  1321.     Æ     format    Get this format.
  1322.     Æ     formatIndex    Value returned by ioNewFormat.
  1323.     Æ     offset    Write format beginning from this offset.
  1324.     Æ     buffPtr    Get data beginning here.
  1325.     ´     buffLen    Specify buffer length to write.
  1326.     ¨    Return value    A noErr code or appropriate error code.
  1327. The marks for each format are kept by the Edition Manager. The format I/O procedure only needs to be able to read or write, beginning at any offset. If you know that your application always reads an entire format sequentially, you can ignore the offset. 
  1328. Reference to the Edition Manager
  1329. This section describes the routines for
  1330. n    initializing the Edition Manager
  1331. n    creating and registering a section
  1332. n    creating and deleting an edition container
  1333. n    setting and locating a format mark
  1334. n    reading in edition data
  1335. n    writing out edition data
  1336. n    closing an edition after reading or writing
  1337. n    displaying dialog boxes
  1338. n    locating a publisher and edition from a subscriber
  1339. n    reading edition container formats
  1340. n    reading and writing non-edition files
  1341. Result codes appear at the end of each function where applicable. In addition to the specific result codes listed, you may receive errors generated by the Alias Manager, File Manager, and Memory Manager.
  1342. Routines
  1343. This section describes the routines you use to
  1344. n    initialize the Edition Manager
  1345. n    create and register a section
  1346. n    create and delete an edition container
  1347. n    set and locate a format mark
  1348. n    read in edition data
  1349. n    write out edition data
  1350. n    close an edition after reading or writing
  1351. n    display dialog boxes
  1352. n    locate a publisher and edition from a subscriber
  1353. n    read and write non-edition files
  1354. Initializing the Edition Manager
  1355. You use the InitEditionPack function to initialize the Edition Manager. Note that you should only call this function once. 
  1356. 1InitEditionPack
  1357. Before calling the InitEditionPack function, be sure to determine whether the Edition Manager is available on your system by using the Gestalt function. The Gestalt selector is gestaltEditionMgrAttr ('edtn').
  1358. FUNCTION InitEditionPack : OSErr;
  1359. DESCRIPTION
  1360. The InitEditionPack function returns an error if the package could not be loaded into the system heap and properly initialized. In addition, you may also receive resource errors. 
  1361. RESULT CODES
  1362. noErr    0    No error
  1363. memFullErr    –108    Could not load package
  1364. Creating and Registering a Section
  1365. You use the NewSection function to create a new section (either publisher or subscriber) and alias record (which is a reference to the edition container from the document containing the publisher or subscriber section). 
  1366. The NewSection function registers a section similar to the way that the RegisterSection function informs the Edition Manager about a section (except that the NewSection function does not resolve an alias to find the edition container).
  1367. When a section needs to be disposed of because the document containing the section is closing, or the user has canceled the section, you need to call the UnRegisterSection function before disposing of the section.
  1368. Using the IsRegisteredSection function, your application must verify that each event received is for a registered section. This is necessary because your application may have just called UnRegisterSection while the event was already being held in the event queue.
  1369. If a user saves a document that contains sections under another name (using Save As) or pastes a portion of a document that contains a section into another document, use the AssociateSection function to update the section’s alias record. 
  1370. 1NewSection
  1371. The NewSection function allocates two handles in the current zone: one handle for the section record and another handle for the alias record. Note that you are responsible for unregistering handles created by the Edition Manager. 
  1372. FUNCTION NewSection (container: EditionContainerSpec;
  1373.                             sectionDocument: FSSpecPtr; 
  1374.                             kind: SectionType; sectionID: LongInt;
  1375.                             initialMode: UpdateMode; 
  1376.                             VAR sectionH: SectionHandle) : OSErr;
  1377. container    The container parameter specifies the edition you want to publish or subscribe to. 
  1378. sectionDocument        
  1379. The sectionDocument parameter contains the volume reference number, directory ID, and filename of the document that contains a section. The sectionDocument parameter can be NIL if your current document has never been saved. If so, when the user finally saves the document, remember to call the AssociateSection function on each section to update its alias record.
  1380. kind    The kind parameter designates the type of section (publisher or subscriber) being created. 
  1381. sectionID    A section ID is a unique number for a section within a document. The sectionID parameter initializes the sectionID field within the new section record. Do not use 0 or –1 for an ID number; these numbers are reserved. If your application copies a section, you need to specify a unique number for the copied section. 
  1382. initialMode    
  1383. The initialMode parameter contains the update mode for the section. For publishers this is either the pumOnSave or pumManual constant, and for subscribers it is either sumAutomatic or sumManual. A subscriber created with sumAutomatic mode automatically receives a Section Read event. To prevent this initial Section Read event, you should set the initialMode parameter to sumManual and then, when NewSection returns, set the mode field of the section record to sumAutomatic.
  1384. sectionH    If the NewSection function fails, the sectionH parameter is set to NIL. If the function is successful, sectionH contains the handle to the allocated section record.
  1385. DESCRIPTION
  1386. Your application receives the multiplePublisherWrn result code if there is another registered publisher to the same edition. Your application receives the notThePublisherWrn result code if another publisher (to the same edition) was the last section to write to the edition. The multiplePublisherWrn result code takes priority over the notThePublisherWrn result code.
  1387. In addition, you may also receive memory and file opening errors.
  1388. RESULT CODES
  1389. noErr         0    No error
  1390. editionMgrInitErr    –450    Manager not initialized
  1391. badSectionErr    –451    Not a valid section type
  1392. badSubPartErr    –454    Bad edition container spec
  1393. multiplePublisherWrn    –460    Already is a publisher
  1394. notThePublisherWrn    –463    Not the publisher
  1395. 1RegisterSection
  1396. The RegisterSection function adds the section record to the Edition Manager’s list of registered sections and tries to allocate a control block. After calling the RegisterSection function, the controlBlock field of the section record is either NIL or a valid control block. 
  1397. FUNCTION RegisterSection (sectionDocument: FSSpec;
  1398.                                   sectionH:SectionHandle; 
  1399.                                   VAR aliasWasUpdated: Boolean) : OSErr;
  1400. sectionDocument    
  1401. The sectionDocument parameter contains the volume reference number, directory ID, and filename of the document that contains a section. 
  1402. sectionH    The sectionH parameter is a handle to the section record for a given section.
  1403. aliasWasUpdated    
  1404. The aliasWasUpdated parameter returns TRUE if the alias for the edition container subscribed to was out of date and was updated. This may occur if the edition file was moved to a new location or was renamed.
  1405. DESCRIPTION
  1406. For a subscriber, the control block is NIL if the RegisterSection function could not locate the edition container being subscribed to. The RegisterSection function then returns either the containerNotFoundWrn or the userCanceledErr result code. For a publisher, if the RegisterSection function could not locate its corresponding edition container, the Edition Manager creates an edition container in the last place the edition was located and creates a control block for it. If the RegisterSection function could not locate a publisher’s corre-sponding edition container or its volume, the control block is NIL. You should never re-register a section that is already registered.
  1407. Note that you can compare control blocks for individual sections. If two sections contain the same control block value, these sections publish or subscribe to the same edition (unless the control block is NIL). The Edition Manager keeps track of how many sections are referencing a control block to know when it can be deallocated. The control block maintains a count of how many sections are referencing it. Each time you use the UnRegisterSection function, the control block subtracts one from the number of sections. When the number of sections reaches 0, the control block is deallocated. 
  1408. Your application receives the multiplePublisherWrn result code if there is another registered publisher to the same edition. Your application receives the notThePublisherWrn result code if another publisher (to the same edition) was the last section to write to the edition. The multiplePublisherWrn result code takes priority over the notThePublisherWrn result code.  
  1409. In addition, you may also receive memory and file opening errors. 
  1410. RESULT CODES
  1411. noErr         0    No error
  1412. userCanceledErr    –128    User chose Cancel from a mount server dialog
  1413.         box
  1414. editionMgrInitErr    –450    Manager not initialized
  1415. badSectionErr    –451    Not valid section type
  1416. multiplePublisherWrn    –460    Already is a publisher
  1417. containerNotFoundWrn    –461    Alias was not resolved
  1418. notThePublisherWrn    –463    Not the publisher
  1419. 1UnRegisterSection
  1420. When a section needs to be disposed of because the document containing the section is closing, or the user has canceled the section, you need to call the UnRegisterSection function before disposing of the section. 
  1421. FUNCTION UnRegisterSection (sectionH: SectionHandle) : OSErr;
  1422. sectionH    The sectionH parameter is a handle to the section record for a given section.
  1423. DESCRIPTION
  1424. The UnRegisterSection function removes the section from the Edition Manager’s list of registered sections. You can then dispose of the section record and alias record with standard Memory and Resource Manager calls. Once unregistered, a section does not receive any events and cannot read or write any data. Depending on your Clipboard strategy, you may want to unregister sections that have been cut into the Clipboard. 
  1425. RESULT CODES
  1426. noErr         0    No error
  1427. fBsyErr    –47    Section doing I/O
  1428. editionMgrInitErr    –450    Manager not initialized
  1429. notRegisteredSectionErr    –452    Not registered
  1430. 1IsRegisteredSection
  1431. Using the IsRegisteredSection function, your application must verify that each event received is for a registered section. This is necessary because your application may have just called UnRegisterSection while the event was already being held in the event queue. 
  1432. FUNCTION IsRegisteredSection (sectionH: SectionHandle) : OSErr;
  1433. sectionH    The sectionH parameter is a handle to the section record for a given section. 
  1434. DESCRIPTION
  1435. The IsRegisteredSection function does not return a Boolean—a noErr result code indicates that a section is registered. 
  1436. RESULT CODES
  1437. noErr         0    No error
  1438. notRegisteredSectionErr    –452    Not registered
  1439. 1AssociateSection
  1440. If a user saves a document that contains sections under another name (using Save As) or pastes a portion of a document that contains a section into another document, use the AssociateSection function to update the section’s alias record.  
  1441. FUNCTION AssociateSection (sectionH: SectionHandle;
  1442.                                     newSectionDocument: FSSpecPtr) : OSErr;
  1443. sectionH    The sectionH parameter is a handle to the section record for a given section. 
  1444. newSectionDocument    
  1445. The newSectionDocument parameter contains the volume reference number, directory ID, and filename of the new document. 
  1446. DESCRIPTION
  1447. The AssociateSection function calls UpdateAlias on the section’s alias record. 
  1448. In addition, you may also receive update alias errors.  
  1449. RESULT CODE
  1450. noErr         0    No error
  1451. Creating and Deleting an Edition Container
  1452. Each time a user creates a new publisher section within a document to an edition that does not already exist, you use the CreateEditionContainerFile function to create an empty edition container. 
  1453. To remove the edition container, use the DeleteEditionContainerFile function. 
  1454. 1CreateEditionContainerFile
  1455. You use the CreateEditionContainerFile function to create an empty edition container.
  1456. FUNCTION CreateEditionContainerFile 
  1457.                             (editionFile: FSSpec; fdCreator: OSType; 
  1458.                                editionFileNameScript: ScriptCode) :                                 OSErr;
  1459. editionFile    
  1460. The editionFile parameter contains the volume reference number, directory ID, and filename for the edition container being created. 
  1461. fdCreator    The fdCreator parameter contains the creator type for the edition.
  1462. editionFileNameScript    
  1463. The editionFileNameScript parameter is the script of the filename. It is returned in the theFileScript field of the edition container specification record. (The new publisher reply record includes a container field for an edition container specification record.)
  1464. DESCRIPTION
  1465. The CreateEditionContainerFile function creates an empty edition container file (it does not contain any formats). This function creates a file type 'edtu'. As soon as you write data to the edition, the type is updated (to 'edtp' for graphics, 'edtt' for text, or 'edts' for sound). If both text and pict are written, the type that was written first determines the file type. If your application has a bundle, you should designate an icon for the appropriate edition types that you can write.
  1466. In addition, you may also receive file creating errors.  
  1467. RESULT CODE
  1468. noErr        0    No error
  1469. editionMgrInitErr    –450    Manager not initialized
  1470. 1DeleteEditionContainerFile
  1471. If a user cancels a publisher section within a document or closes a document containing a newly created publisher without saving, you need to remove the edition container. 
  1472. To locate the appropriate edition container to be deleted, use the GetEditionInfo function. You use the UnRegisterSection function (only after using the GetEditionInfo function) to unregister the section record and alias record of the publisher being canceled. See “Locating a Publisher and Edition From a Subscriber” later in this chapter for detailed information on the GetEditionInfo function. See “Creating and Registering a Section” earlier in this chapter for detailed information on the UnRegisterSection function.
  1473. To remove the edition container, use the DeleteEditionContainerFile function. 
  1474. FUNCTION DeleteEditionContainerFile (editionFile: FSSpec) : OSErr;
  1475. editionFile    
  1476. The editionFile parameter contains the volume reference number, directory ID, and filename for the edition container being deleted.
  1477. DESCRIPTION
  1478. If the user cancels a publisher, do not call the DeleteEditionContainerFile function until the user saves the document. This allows the user to undo changes and revert to the last saved version of the document.
  1479. The DeleteEditionContainerFile function only deletes the edition container if there is no registered publisher. You need to unregister a publisher before you can delete its corresponding edition container.
  1480. You should use the DeleteEditionContainerFile function even if there are subscribers to the edition. When a subscriber section tries to read in data, it receives an error. 
  1481. In addition, you may also receive file deleting errors. 
  1482. RESULT CODES
  1483. noErr         0    No error
  1484. editionMgrInitErr    –450    Manager not initialized
  1485. Setting and Locating a Format Mark
  1486. Use the SetEditionFormatMark function to set the current mark for a section format and use the GetEditionFormat Mark function to locate the current marker for a particular format. 
  1487. 1SetEditionFormatMark
  1488. A format mark indicates the next position of a read or write operation. Initially, a mark defaults to 0. After reading or writing data, the format mark is set past the last position written to or read from. 
  1489. FUNCTION SetEditionFormatMark (whichEdition: EditionRefNum;
  1490.                                          whichFormat: FormatType;
  1491.                                          setMarkTo: LongInt) : OSErr;
  1492. whichEdition    
  1493. The whichEdition parameter is the reference number for the edition. 
  1494. whichFormat    
  1495. The whichFormat parameter indicates the format type for the edition.
  1496. setMarkTo    The setMarkTo parameter is the offset for the next read or write for this format. 
  1497. RESULT CODES
  1498. noErr         0    No error
  1499. rfNumErr    –51    Bad edition reference number
  1500. noTypeErr    –102    Unknown format (subscriber only)
  1501. editionMgrInitErr    –450    Manager not initialized
  1502. 1GetEditionFormatMark
  1503. Use the GetEditionFormat Mark function to locate the current marker for a particular format. 
  1504. FUNCTION GetEditionFormatMark (whichEdition: EditionRefNum;
  1505.                                          whichFormat: FormatType; 
  1506.                                          VAR currentMark: LongInt) :                                 OSErr;
  1507. whichEdition    
  1508. The whichEdition parameter is the reference number for the edition. 
  1509. whichFormat    
  1510. The whichFormat parameter indicates the format type for the edition.
  1511. currentMark    
  1512. The currentMark parameter is the mark for the format. 
  1513. DESCRIPTION
  1514. If the edition does not support the format specified in the whichFormat parameter, you receive a noTypeErr result code. 
  1515. RESULT CODES
  1516. noErr         0    No error
  1517. rfNumErr    –51    Bad edition reference number
  1518. noTypeErr    –102    Unknown format
  1519. editionMgrInitErr    –450    Manager not initialized
  1520. Reading in Edition Data
  1521. To initiate the reading of data from an edition (for a subscriber), use the OpenEdition function. 
  1522. Use the EditionHasFormat function to learn in which formats the edition data is available.
  1523. You use the ReadEdition function to read data from an edition. This function reads from the current mark for the specified format.
  1524. 1OpenEdition
  1525. To initiate the reading of data from an edition (for a subscriber), use the OpenEdition function.
  1526. FUNCTION OpenEdition (subscriberSectionH: SectionHandle; VAR 
  1527.                              refNum: EditionRefNum) : OSErr;
  1528. subscriberSectionH    
  1529. The subscriberSectionH parameter is a handle to the section record for a given section. 
  1530. refNum    The refNum parameter returns the reference number for the edition.
  1531. DESCRIPTION
  1532. Multiple subscribers can each call the OpenEdition function simultaneously (each call returns a different reference number) and read data from a single edition. If a publisher (located on a different machine) is writing to an edition when you use the OpenEdition function, you receive an flLckedErr result code.
  1533. In addition, you may also receive memory, file opening, and file reading errors.  
  1534. RESULT CODES
  1535. noErr         0    No error
  1536. flLckedErr    –45    Publisher writing to an edition
  1537. permErr    –54    Not a subscriber
  1538. editionMgrInitErr    –450    Manager not initialized
  1539. 1EditionHasFormat
  1540. Use the EditionHasFormat function to learn in which formats the edition data is available. 
  1541. FUNCTION EditionHasFormat (whichEdition: EditionRefNum;
  1542.                                     whichFormat:FormatType; 
  1543.                                     VAR formatSize: Size) : OSErr;
  1544. whichEdition    
  1545. The whichEdition parameter is the reference number for the edition. 
  1546. whichFormat    
  1547. The whichFormat parameter indicates the format type that you are requesting. For the whichFormat parameter, you should decide which formats to read in the same way that you do when using paste from the Scrap Manager. You can also get a list of all the available formats and their respective lengths by reading the kFormatListFormat ('fmts') format. 
  1548. formatSize    The formatSize parameter specifies the format length.
  1549. DESCRIPTION
  1550. If the requested format is available, this function returns noErr, and the formatSize parameter returns the size of the data in the specified format or kFormatLengthUnknown (–1), which signifies that the size is unknown. You should therefore continue to read the format until there is no more data.
  1551. Be aware that the EditionHasFormat function may return kFormatLengthUnknown for the length of the format. 
  1552. RESULT CODES
  1553. noErr         0    No error
  1554. rfNumErr    –51    Bad edition reference number
  1555. noTypeErr    –102    Format not available
  1556. editionMgrInitErr    –450    Manager not initialized
  1557. 1ReadEdition
  1558. Use the ReadEdition function to read data from an edition. This function reads from the current mark for the specified format. 
  1559. FUNCTION ReadEdition (whichEdition: EditionRefNum; 
  1560.                              whichFormat:                 FormatType; buffPtr: UNIV Ptr;
  1561.                              VAR buffLen: Size) : OSErr;
  1562. whichEdition    
  1563. The whichEdition parameter is the reference number for the edition. 
  1564. whichFormat    
  1565. The whichFormat parameter indicates the format type that you want to read. 
  1566. buffPtr    The buffPtr parameter is a pointer to the buffer into which you want to read the data.
  1567. buffLen    The buffLen parameter is the number of bytes that you want to read into the buffer. 
  1568. DESCRIPTION
  1569. The buffLen parameter is also a return value that returns the total number of bytes read into the buffer. If the buffLen parameter returns a value smaller than the value you have specified, there is no additional data to read, and the ReadEdition function returns a noErr result code. If you use the ReadEdition function after all data is read in, the ReadEdition function returns an eofErr result code.
  1570. You can read data from an edition while a publisher on the same machine is writing data to the same edition. The data that you are reading is the old edition (not the data that the publisher is writing). If the publisher finishes writing data before you are through reading the old edition data, the ReadEdition function returns an abortErr result code. If the ReadEdition function returns an abortErr result code, you should stop trying to read data and use the CloseEdition function with the successful parameter set to FALSE. 
  1571. In addition, you may also receive file reading errors. 
  1572. RESULT CODES
  1573. noErr         0    No error
  1574. abortErr    –27    Publisher has written a new edition
  1575. eofErr    –39    No more data of that format
  1576. rfNumErr    –51    Bad edition reference number
  1577. noTypeErr    –102    Format not available
  1578. editionMgrInitErr    –450    Manager not initialized
  1579. Writing out Edition Data
  1580. To initiate the writing of data from a publisher to its edition container, use the OpenNewEdition function. 
  1581. Use the WriteEdition function to write data to an edition.
  1582. 1OpenNewEdition
  1583. To initiate the writing of data from a publisher to its edition container, use the OpenNewEdition function.
  1584. FUNCTION OpenNewEdition (publisherSectionH: SectionHandle;
  1585.                                  fdCreator:OSType;     
  1586.                                     publisherSectionDocument: FSSpecPtr; 
  1587.                                  VAR     refNum: EditionRefNum) : OSErr;
  1588. publisherSectionH    
  1589. The publisherSectionH parameter is the publisher section that is writing to the edition. 
  1590. fdCreator    The fdCreator parameter is the Finder creator type of the new edition icon.
  1591. publisherSectionDocument    
  1592. The publisherSectionDocument parameter is the document that contains the publisher. This parameter is used to create an alias from the edition to the publisher’s document. If you pass NIL for publisherSectionDocument, an alias is not made in the edition file.
  1593. refNum    The refNum parameter returns the reference number for the edition. This parameter is necessary for subsequent calls to WriteEdition, SetEditionFormatMark, and CloseEdition to specify which publisher is writing its data to an edition. If the edition cannot be opened for writing because there is another publisher writing to it, or because the file system does not allow writing, an error is returned and refNum is set to NIL. 
  1594. DESCRIPTION
  1595. The OpenNewEdition function returns an flLckdErr result code if there is a subscriber on another machine reading data from the same edition. The OpenNewEdition function returns a permErr result code if there is a registered publisher to that edition on another machine. 
  1596. The Edition Manager allows two registered publishers that are located on the same machine to write to the same edition. Note that multiple publishers cannot write to the same edition simultaneously—only one publisher can write to an edition at a given time.  
  1597. In addition, you may also receive file creating, file opening, file reading, resolve alias, and memory errors. 
  1598. RESULT CODES
  1599. noErr    0    No error
  1600. flLckdErr    –45    Edition in use by another section
  1601. permErr    –54    Registered publisher on another machine
  1602. wrPermErr    –61    Not a publisher
  1603. editionMgrInitErr    –450    Manager not initialized    
  1604. 1WriteEdition
  1605. Use the WriteEdition function to write data to an edition. This function begins writing at the current mark for the specified format. 
  1606. FUNCTION WriteEdition (whichEdition: EditionRefNum; 
  1607.                               whichFormat: FormatType; 
  1608.                               buffPtr: UNIV Ptr; buffLen: Size) : OSErr;
  1609. whichEdition    
  1610. The whichEdition parameter is the reference number for the edition. 
  1611. whichFormat    
  1612. The whichFormat parameter indicates the format type that you want to write. 
  1613. buffPtr    The buffPtr parameter is a pointer to the buffer that you are writing into the edition. 
  1614. buffLen    The buffLen parameter is the number of bytes that you want to write. If the data cannot be entirely written to the edition, the WriteEdition function returns an error.
  1615. DESCRIPTION
  1616. In addition, you may also receive file writing and memory errors.  
  1617. RESULT CODES
  1618. noErr         0    No error
  1619. rfNumErr    –51    Bad edition reference number
  1620. editionMgrInitErr    –450    Manager not initialized
  1621. Closing an Edition After Reading or Writing
  1622. After finishing reading from or writing to an edition, use the CloseEdition function to close the edition. 
  1623. 1CloseEdition
  1624. Use the CloseEdition function to close the edition after you finish reading from or writing to an edition.
  1625. FUNCTION CloseEdition (whichEdition: EditionRefNum; 
  1626.                               successful: Boolean)                     : OSErr;
  1627. whichEdition    
  1628. The whichEdition parameter is the reference number for the edition. 
  1629. successful    The successful parameter indicates whether your application was successful in reading or writing data to the edition.
  1630. DESCRIPTION
  1631. When a subscriber successfully finishes reading data from the edition, the CloseEdition function takes the modification date of the edition file that you have read and puts it in the mdDate field of the subscriber’s section record. This indicates that the data contained in the edition and the subscriber section within the document are the same.
  1632. When a subscriber is unsuccessful in reading data from an edition (because there is not enough memory, or you didn’t find a format that you can read), set the successful parameter to FALSE. The CloseEdition function then closes the edition, but does not set the mdDate field. This implies that the subscriber is not updated with the latest edition.
  1633. When a publisher successfully finishes writing data to an edition, the CloseEdition function makes the data that the publisher has written to the edition available to any subscribers and sets the corresponding edition file’s modification date (ioFlMdDat) to the mdDate field of the publisher’s section record. The Edition Manager then sends a Section Read event to all current subscribers set to automatic update mode. At this point, the file type of the edition file is set based on the first known format that the publisher wrote.
  1634. When a publisher is unsuccessful in writing data to an edition, the CloseEdition function discards what the publisher has written to the edition. The data contained in the edition prior to writing remains unchanged, and Section Read events are not sent to subscribers. 
  1635. In addition, you may also receive file closing errors. 
  1636. RESULT CODES
  1637. noErr         0    No error
  1638. rfNumErr    –51    Bad edition reference number
  1639. editionMgrInitErr    –450    Manager not initialized
  1640. Displaying Dialog Boxes
  1641. The Edition Manager supports three dialog boxes: publisher, subscriber, and options dialog boxes. Your application can display simple dialog boxes that appear centered on the user’s screen, or you can customize your dialog boxes.
  1642. Use the GetLastEditionContainerUsed function to get the default edition to display. 
  1643. Use the NewSubscriberDialog function to display the subscriber dialog box on the user’s screen and use the NewPublisherDialog function to display the publisher dialog box on the user’s screen. Unlike the Standard File routines, the NewPublisherDialog and the NewSubscriberDialog functions allow you to specify the initial volume reference number and directory ID so that there can be one default location for editions for all applications.
  1644. You use the SectionOptionsDialog function to display the publisher options and subscriber options dialog boxes on the user’s screen.
  1645. The NewSubscriberExpDialog, NewPublisherExpDialog, and SectionOptionsExpDialog functions are the same as the simple dialog functions but have five additional parameters.
  1646. 1GetLastEditionContainerUsed
  1647. Use the GetLastEditionContainerUsed function to get the default edition to display. This function allows a user to easily subscribe to the data recently published. 
  1648. FUNCTION GetLastEditionContainerUsed 
  1649.                             (VAR container:                     EditionContainerSpec) : OSErr;
  1650. container    If the GetLastEditionContainer function locates the last edition for which a section was created, the container parameter contains its volume reference number, directory ID, filename, and part, and returns a noErr result code. (The last edition created is associated with the last time that your application or another application located on the same machine used the NewSection function.) 
  1651. DESCRIPTION
  1652. If the last edition used is missing, the GetLastEditionContainerUsed function returns an fnfErr result code, but still returns the correct volume reference number and directory ID that you should use for the NewSubscriberDialog function.
  1653. Pass the information from the GetLastEditionContainerUsed function to the NewSubscriberDialog function. 
  1654. RESULT CODES
  1655. noErr         0    No error
  1656. fnfErr    –43    Edition container not found
  1657. editionMgrInitErr    –450    Manager not initialized
  1658. 1NewSubscriberDialog
  1659. Use the NewSubscriberDialog function to display the subscriber dialog box on the user’s screen. 
  1660. FUNCTION NewSubscriberDialog 
  1661.                             (VAR reply: NewSubscriberReply) : OSErr;
  1662. reply    The reply parameter contains the new subscriber reply record.
  1663. TYPE NewSubscriberReply = 
  1664.     RECORD
  1665.         canceled:                    Boolean;                            {user canceled }
  1666.                                                         { dialog box}
  1667.         formatsMask:                    SignedByte;                            {formats required}
  1668.         container:                    EditionContainerSpec;                            {edition selected}
  1669.     END;
  1670. Field desciptions
  1671. canceled    If the NewSubscriberDialog function returns with the canceled field set to TRUE, the user canceled the dialog box. Otherwise, this field is FALSE and the container field holds the edition container for the new subscriber. 
  1672. formatsMask    The formatsMask field indicates which edition format type (text, graphics, and sound) to display within the subscriber dialog box. You can set the formatsMask field to the following constants: kTEXTformatMask (1), kPICTformatMask (2), or ksndFormatMask (4). To support a combination of formats, add the constants together. For example, a formatsMask of 3 displays both graphics and text edition format types in the subscriber dialog box. 
  1673. container    If the canceled field is FALSE, the container field holds the edition container for the new subscriber.
  1674.     DESCRIPTION
  1675. The NewSubscriberDialog function (which is based on the CustomGetFile procedure described in the Standard File Package chapter in this volume) switches to the volume refer-ence number and directory ID and selects the filename of the edition container that you passed in. Use the GetLastEditionContainerUsed function to set the edition container to the last edition that was either published or subscribed to. This allows the user to publish and then easily subscribe.
  1676. Note that if an edition does not contain either 'PICT', 'TEXT', or 'snd ' data, it will not be seen by the NewSubscriberDialog function (unless you install an opener that adds it using eoCanSubscribe).
  1677. RESULT CODES
  1678. noErr         0    No error
  1679. editionMgrInitErr    –450    Package not initialized
  1680. badSubPartErr    –454    Bad edition container spec
  1681. 1NewPublisherDialog
  1682. Use the NewPublisherDialog function to display the publisher dialog box on the user’s screen. 
  1683. FUNCTION NewPublisherDialog 
  1684.                         (VAR reply: NewPublisherReply) : OSErr;
  1685. reply    The reply parameter contains a new publisher reply record.
  1686. TYPE NewPublisherReply = 
  1687.     RECORD
  1688.         canceled:                    Boolean;                    {user canceled dialog box}    
  1689.         replacing:                    Boolean;                    {user chose existing } 
  1690.                                                 { filename for an edition}
  1691.         usePart:                    Boolean;                    {always false in version 7.0}
  1692.         preview:                    Handle;                    {handle to 'prvw', 'PICT', }
  1693.                                                 { 'TEXT', or 'snd' data} 
  1694.         previewFormat:                    FormatType;                    {type of preview}
  1695.         container:                    EditionContainerSpec;    
  1696.                                                 {edition chosen}
  1697.     END;
  1698. Field descriptions
  1699. canceled    Upon return of the NewPublisherDialog function, the canceled and replacing fields are set. If the canceled field is set to TRUE, the user canceled the dialog box. If the replacing field is TRUE, the user chose an existing filename from the list of available editions and confirmed this replacement. 
  1700. replacing    If the replacing field is TRUE, do not call the CreateEditionContainerFile function, which creates a new edition container. 
  1701. usePart    The usePart field must be set to FALSE before calling the NewPublisherDialog function.
  1702. preview    Set the preview field to be a handle to 'prvw', 'PICT', 'TEXT', or 'snd ' data. 
  1703. previewFormat    
  1704. Set the previewFormat field to indicate which type of data the handle references.
  1705. container    The container field contains the volume reference number, directory ID, and filename for the edition that the user selected. 
  1706. DESCRIPTION
  1707. The NewPublisherDialog function (which is based on the CustomPutFile procedure described in the Standard File Package chapter) switches to the volume reference number and directory ID and sets the text edit field to the filename of the edition container that you passed in. Set the fileName field of the file system specification record to be the default name of the edition file. (The new publisher reply record includes a container field for an edition container specification record, and the edition container specification record includes a field [theFile] for a file system specification record.) See “Creating a Publisher” earlier in this chapter for information on the default file specification. 
  1708. You should deallocate the handle referenced by the preview field to free up memory. 
  1709. RESULT CODES
  1710. noErr         0    No error
  1711. editionMgrInitErr    –450    Package not initialized
  1712. badSubPartErr    –454    Bad edition container spec
  1713. 1SectionOptionsDialog
  1714. Use the SectionOptionsDialog function to display the publisher options and subscriber options dialog boxes on the user’s screen. 
  1715. FUNCTION SectionOptionsDialog  
  1716.                             (VAR reply: SectionOptionsReply) : OSErr;
  1717. reply    The reply parameter contains a section options reply record.
  1718. TYPE SectionOptionsReply = 
  1719.     RECORD
  1720.         canceled:                Boolean;                        {user canceled dialog box}    
  1721.         changed:                Boolean;                        {changed the section record}    
  1722.         sectionH:                SectionHandle;                        {handle to the specified }
  1723.                                                 { section record}
  1724.         action:                ResType;                        {action codes}    
  1725.     END;
  1726. Field descriptions
  1727. canceled    Upon return of the SectionOptionsDialog function, the canceled and changed fields are set. If the canceled parameter is set to TRUE, the user canceled the dialog box. Otherwise, this parameter is FALSE. 
  1728. changed    If the changed parameter is TRUE, the user changed the section record. For example, the update mode may have changed.
  1729. sectionH    Set the sectionH parameter to the handle to the section record for the section the user selected.
  1730. action    The action field contains the code for one of five user actions: action code is 'read' for user selection of the Get Edition Now button, action code is 'writ' for user selection of the Send Edition Now button, action code is 'goto' for user selection of the Open Publisher button, action code is 'cncl' for user selection of the Cancel Publisher or Cancel Subscriber button, action code is '      ' ($20202020) for user selection of the OK button
  1731. DESCRIPTION
  1732. Note that you may receive memory errors. 
  1733. 1NewSubscriberExpDialog, NewPublisherExpDialog, SectionOptionsExpDialog
  1734. The NewSubscriberExpDialog, NewPublisherExpDialog, and SectionOptionsExpDialog functions are the same as the simple dialog functions but have five additional parameters. These additional parameters allow you to add items to the bottom of the dialog boxes, apply alternate mapping of events to item hits, apply alternate meanings to the item hits, and choose the location of the dialog boxes.  
  1735. FUNCTION NewSubscriberExpDialog 
  1736.                             (VAR reply: NewSubscriberReply; where:
  1737.                               Point;expansionDITLresID: Integer; 
  1738.                              dlgHook: ExpDlgHookProcPtr; filterProc:
  1739.                               ExpModalFilterProcPtr; 
  1740.                              yourDataPtr: UNIV Ptr) : OSErr;
  1741. FUNCTION NewPublisherExpDialog 
  1742.                             (VAR reply: NewPublisherReply; where: 
  1743.                              Point; expansionDITLresID: Integer; 
  1744.                              dlgHook: ExpDlgHookProcPtr; filterProc: 
  1745.                              ExpModalFilterProcPtr; 
  1746.                              yourDataPtr: UNIV Ptr) : OSErr;
  1747. FUNCTION SectionOptionsExpDialog 
  1748.                             (VAR reply: SectionOptionsReply; where: 
  1749.                              Point; expansionDITLresID: Integer; 
  1750.                              dlgHook: ExpDlgHookProcPtr; 
  1751.                              filterProc: ExpModalFilterProcPtr; 
  1752.                              yourDataPtr: UNIV Ptr) : OSErr;
  1753. reply    The reply parameter contains a pointer from the new subscriber reply, new publisher reply, or the section options reply records.
  1754. where    You can automatically center the dialog box by passing (–1, –1) in the where parameter. 
  1755. expansionDITLresID    
  1756. The expansionDITLresID parameter should be 0 or a valid dialog item list ('DITL') resource ID. This integer is the ID of a dialog item list whose items are appended to the end of the standard dialog item list. The dialog items keep their relative positions, but they are moved as a group to the bottom of the dialog box. See the Dialog Manager chapter in Volume I for additional information on dialog item lists.
  1757. dlgHook    The dlgHook parameter should be a valid expandable dialog hook procedure pointer or NIL. This procedure is called after each call to the ModalDialog procedure. The dialog hook procedure takes the appropriate action, such as filling in a check box. The itemOffset parameter to the procedure is the number of items in the dialog item list before your expansion dialog items. You need to subtract the item offset from the item hit to get the relative item number in the expansion dialog item list. The return value from the dialog hook procedure is the absolute item number. 
  1758. filterProc    The filterProc parameter should be a valid expandable modal filter procedure pointer or NIL. This procedure is called by the ModalDialog procedure. This function allows you to map real events (such as a mouse-down event) to an item hit (such as clicking a Cancel button). For instance, you may want to map a keyboard equivalent to an item hit.
  1759. yourDataPtr    
  1760. The yourDataPtr parameter is reserved for your use. It is passed back to your hook and modal-dialog filter function. This parameter does not have to be of type Ptr—it can be any 32-bit quantity that you want. In Pascal, you can pass in register A6 for yourDataPtr, and make dialog hook and filter procedure local functions without the last parameter. The stack frame is set up properly for these functions to access their parent local variables. See the Standard File Package chapter in this volume for detailed information.
  1761. DESCRIPTION
  1762. For the NewPublisherExpDialog and NewSubscriberExpDialog functions, all the pseudo-items for the Standard File Package such as hookFirstCall(–1), hookNullEvent(100), hookRebuildList(101), and hookLastCall(–2) can be used, as well as hookRedrawPreview(150). 
  1763. For the SectionOptionsExpDialog function, the only valid pseudo-items are hookFirstCall(–1), hookNullEvent(100), hookLastCall(–2), emHookRedrawPreview(150), emHookCancelSection(160), emHookGoToPublisher(161), emHookGetEditionNow(162), emHookSendEditionNow(162), emHookManualUpdateMode(163), and emHookAutoUpdateMode(164).
  1764. If you have an expandable dialog hook function, it must contain the following parameters.
  1765. FUNCTION MyExpDlgHook (itemOffset: Integer; itemHit: Integer;
  1766.                                 theDialog: DialogPtr; 
  1767.                                  yourDataPtr: Ptr) : Integer;
  1768. If you have an expandable modal-dialog filter function, it must contain the following parameters. 
  1769. FUNCTION MyExpModalFilter (theDialog: DialogPtr; 
  1770.                                     VAR theEvent: EventRecord; 
  1771.                                     itemOffset: Integer; 
  1772.                                     VAR itemHit: Integer; 
  1773.                                     yourDataPtr: Ptr) : Boolean;
  1774. Locating a Publisher and Edition From a Subscriber
  1775. The GetEditionInfo function returns information about a section’s edition such as its location, last modification date, creator, and type. 
  1776. Use the GetEditionInfo function to locate an edition container.
  1777. 1GetEditionInfo
  1778. Use the GetEditionInfo function to obtain information about a section’s edition such as its location, last modification date, creator, and type.
  1779. FUNCTION GetEditionInfo                             
  1780.                             (sectionH: SectionHandle; 
  1781.                             VAR editionInfo: EditionInfoRecord) : OSErr;
  1782. sectionH    The sectionH parameter is a handle to the section record for a given section. 
  1783. editionInfo    
  1784. The editionInfo parameter contains an edition information record. The GetEditionInfo function returns the public information contained in the section’s control block.
  1785. DESCRIPTION
  1786. The Edition Manager synchronizes to ensure that the existing edition name corresponds to the Finder’s existing edition name. If the controlblock field of the section record is NIL, or the edition cannot be located, the GetEditionInfo function returns an fnfErr result code.
  1787. TYPE EditionInfoRecord = 
  1788.     RECORD
  1789.         crDate:                TimeStamp;                            {date edition container }
  1790.                                                     { was created}
  1791.         mdDate:                TimeStamp;                            {date of last change}
  1792.         fdCreator:                OSType;                            {file creator}
  1793.         fdType:                OSType;                            {file type}
  1794.         container:                EditionContainerSpec;                            {the edition}
  1795.     END;
  1796. crDate    The crDate field contains the creation date of the edition. 
  1797. mdDate    The mdDate field contains the modification date of the edition.
  1798. fdCreator    The fdCreator and fdType fields are the creator and type of the edition file. 
  1799. fdType    The fdCreator and fdType fields are the creator and type of the edition file. 
  1800. container    The container field includes a volume reference number, directory ID, filename, script, and part number for the edition.
  1801. RESULT CODES
  1802. noErr         0    No error
  1803. fnfErr    –43    Not registered or file moved
  1804. editionMgrInitErr    –450    Manager not initialized
  1805. 1GoToPublisherSection
  1806. When the user wants to locate the publisher for a particular subscriber (by choosing Open Publisher in the subscriber options dialog box), the action code 'goto' is returned to you.
  1807. Use the GetEditionInfo function to find the edition container. You should next use the GoToPublisherSection function to open the document containing the publisher. 
  1808. Use the GoToPublisherSection function to resolve the alias in the edition to find the document containing its publisher. In general, this function internally uses the GetStandardFormats function to get the alias to the publisher document and then resolves the alias. It next sends the Finder an Apple event to open the document (which launches its application if necessary) and, after the publisher is registered, sends a Section Scroll event to the publisher. 
  1809. As an optimization, if there is a registered publisher, the GoToPublisherSection function simply sends a Section Scroll event to the publisher. 
  1810. If the edition does not contain an alias and there are no registered publishers, then the GoToPublisherSection function sends an Open Documents event to open the edition to the creating application.
  1811. If the edition container is not an edition file (such as when you are using bottlenecks to subscribe to non-edition files), the GoToPublisherSection function sends the Finder an Apple event to open that file. 
  1812. FUNCTION GoToPublisherSection 
  1813.                                 (container: EditionContainerSpec) : OSErr;
  1814. container    The container parameter includes the edition volume reference number, directory ID, and filename. You obtain the edition container by calling the GetEditionInfo function. 
  1815. DESCRIPTION
  1816. In addition, you may also receive resolve alias errors. 
  1817. RESULT CODES
  1818. noErr         0    No error
  1819. editionMgrInitErr    –450    Manager not initialized
  1820. badSubPartErr    –454    Invalid edition container
  1821. Edition Container Formats
  1822. The Edition Manager calls the GetStandardFormats function to get the alias used in the GoToPublisherSection function and to get the preview shown in the subscriber dialog box. You probably do not need to call this function directly. 
  1823. 1GetStandardFormats
  1824. You probably do not need to call the GetStandardFormats function directly because the Edition Manager calls this function.
  1825. FUNCTION GetStandardFormats 
  1826.                     (container: EditionContainerSpec; 
  1827.                      VAR previewFormat: FormatType;
  1828.                         preview, publisherAlias, formats:Handle) : OSErr;
  1829. container    The container parameter is a pointer to the edition volume reference number, directory ID, filename, and part.
  1830. previewFormat    
  1831. The first format that was written returns in the preview handle and the previewFormat parameter is set to its type. 
  1832. preview    The preview parameter tries to find one of four formats: 'prvw', 'PICT', 'TEXT', or 'snd '. 
  1833. publisherAlias    
  1834. The publisherAlias parameter reads the format kPublisherDocAliasFormat ('alis').
  1835. formats    The formats parameter reads the virtual format kFormatListFormat ('fmts'). 
  1836. DESCRIPTION
  1837. You should pass in valid handles for the formats that you want and NIL for the formats that you don’t want. The handles are resized to the size of the data. 
  1838.  If one of the requested formats cannot be found, GetStandardFormats returns a noTypeErr result code. 
  1839. RESULT CODES
  1840. noErr         0    No error
  1841. noTypeErr    –102    Edition container not found
  1842. editionMgrInitErr    –450    Manager not initialized
  1843. Reading and Writing Non-Edition Files
  1844. The Edition Manager never opens or closes an edition container directly—it calls the current edition opener. See “Subscribing to Non-Edition Files” earlier in this chapter for additional information.
  1845. To override the standard opener function, you should create an opener function that contains the following parameters. 
  1846. FUNCTION MyOpener (selector: EditionOpenerVerb; 
  1847.                          VAR PB: EditionOpenerParamBlock) : OSErr;
  1848. When this function is called by the Edition Manager, the selector parameter is set to one of the edition opener verbs (eoOpen, eoClose, eoOpenNew, eoCloseNew, eoCanSubscribe). The PB parameter contains an edition opener parameter block record.
  1849. Use the GetEditionOpenerProc function to locate the current edition opener procedure and use the SetEditionOpenerProc function to provide your own edition opener procedure. 
  1850. Use the CallEditionOpenerProc function to call an edition opener procedure pointer and use the CallFormatIOProc function to call a format IO procedure.
  1851. 1GetEditionOpenerProc
  1852. Use the GetEditionOpenerProc function to locate the current edition opener procedure. 
  1853. FUNCTION GetEditionOpenerProc 
  1854.                             (VAR opener: EditionOpenerProcPtr) : OSErr;
  1855. opener    The opener parameter returns the pointer to the current edition opener procedure.
  1856. 1SetEditionOpenerProc
  1857. Use the SetEditionOpenerProc function to provide your own edition opener procedure. 
  1858. FUNCTION SetEditionOpenerProc 
  1859.                             (opener: EditionOpenerProcPtr) : OSErr;
  1860. opener    The opener parameter is a pointer to the edition opener procedure that you are providing.
  1861. 1CallEditionOpenerProc
  1862. Use the CallEditionOpenerProc function to call an edition opener procedure pointer. 
  1863. FUNCTION CallEditionOpenerProc 
  1864.                             (selector: EditionOpenerVerb; 
  1865.                              VAR PB: EditionOpenerParamBlock;
  1866.                              routine: EditionOpenerProcPtr) : OSErr;
  1867. selector    When this function is called by the Edition Manager, the selector parameter is set to one of the edition opener verbs (eoOpen, eoClose, eoOpenNew, eoCloseNew, eoCanSubscribe). 
  1868. PB    The PB parameter contains an edition opener parameter block record. 
  1869. routine    The routine parameter is a pointer to an edition opener procedure.
  1870. TYPE EditionOpenerParamBlock = 
  1871.     RECORD
  1872.         info:                    EditionInfoRecord;                            {edition container to }
  1873.                                                         { be subscribed to}    
  1874.         sectionH:                    SectionHandle;                            {publisher or }
  1875.                                                         { subscriber }
  1876.                                                         { requesting open}
  1877.         document:                    FSSpecPtr;                            {document passed}
  1878.         fdCreator:                    OSType;                            {Finder creator type}    
  1879.         ioRefNum:                    LongInt;                            {reference number}    
  1880.         ioProc:                    FormatIOProcPtr;                            {routine to read }
  1881.                                                         { formats}    
  1882.         success:                    Boolean;                            {reading or writing }
  1883.                                                         { was successful}
  1884.         formatsMask:                    SignedByte;                            {formats required to }
  1885.                                                         { subscribe}    
  1886.     END;
  1887. To override the standard reading and writing functions, you should create an IO function that contains the following parameters. 
  1888. FUNCTION MyIO (selector: FormatIOVerb; 
  1889.                     VAR PB: FormatIOParamBlock) :                 OSErr;
  1890. Set the selector parameter to one of the format I/O verbs (ioHasFormat, ioReadFormat, ioNewFormat, ioWriteFormat). The PB parameter contains a format I/O parameter block record.
  1891. 1CallFormatIOProc
  1892. Use the CallFormatIOProc function to call a format IO procedure. 
  1893. FUNCTION CallFormatIOProc (selector: FormatIOVerb; 
  1894.                                     VAR PB:FormatIOParamBlock; 
  1895.                                     routine: FormatIOProcPtr)                         : OSErr;
  1896. selector    Set the selector parameter to one of the format I/O verbs (ioHasFormat, ioReadFormat, ioNewFormat, ioWriteFormat). 
  1897. PB    The PB parameter contains a format I/O parameter block record.
  1898. routine    The routine parameter is a pointer to a format I/O procedure. 
  1899. TYPE FormatIOParamBlock = 
  1900.     RECORD
  1901.         ioRefNum:                    LongInt;                    {reference number}
  1902.         format:                    FormatType;                    {edition format type}
  1903.         formatIndex:                    LongInt;                    {opener-specific enumeration } 
  1904.                                                 { of formats}
  1905.         offset:                    LongInt;                    {offset into format}
  1906.         buffPtr:                    Ptr;                    {data starts here}
  1907.         buffLen:                    LongInt;                    {length of data}
  1908.     END;    
  1909. Summary of the Edition Manager
  1910. Constants
  1911. CONST        {resource types}
  1912.         rSectionType                                        = 'sect';                {resource type for a }
  1913.                                                                 { section}
  1914.  
  1915.         {section types}
  1916.         stSubscribe    r                                    = $01;                {subscriber section type}
  1917.         stPublisher                                        = $0A;                {publisher section type} 
  1918.  
  1919.         {update modes}
  1920.         sumAutomatic                                        = 0;                {subscriber receives new } 
  1921.                                                                 { editions automatically}
  1922.         sumManual                                        = 1;                {subscriber receives new } 
  1923.                                                                 { editions manually}
  1924.         pumOnSave                                        = 0;                {publisher sends new } 
  1925.                                                                 { editions on save}
  1926.         pumManual                                        = 1;                {publisher does not send } 
  1927.                                                                 { new editions until user }
  1928.                                                                 { request}
  1929.         {edition container subpart number}
  1930.         kPartsNotUsed                                        = 0;                {edition is the whole file}
  1931.         kPartNumberUnknown                                        = -1;                {not used in version 7.0} 
  1932.  
  1933.         {preview size}
  1934.         kPreviewWidth                                        = 120;                {preview width} 
  1935.         kPreviewHeight                                        = 120;                {preview height}
  1936.  
  1937.         {special formats}
  1938.         kPublisherDocAliasFormat                                        = 'alis';                {alias record from the } 
  1939.                                                                 { edition to publisher} 
  1940.         kPreviewFormat                                        = 'prvw';                {'PICT' thumbnail sketch}
  1941.         kFormatListFormat                                        = 'fmts';                {list of all available }
  1942.                                                                 { formats and their sizes}
  1943.  
  1944.         {bits for formatMask}
  1945.         kPICTformatMask                                        = 1;                {graphics format}
  1946.         kTEXTformatMask                                        = 2;                {text format}
  1947.         ksndFormatMask                                        = 4;                {sound format}
  1948.  
  1949.         {Finder types for edition files}
  1950.         kPICTEditionFileType                                        = 'edtp';                {contains 'PICT', }
  1951.         kTEXTEditionFileType                                        = 'edtt';                { 'TEXT', and }
  1952.         ksndEditionFileType                                        = 'edts';                { 'snd ' file types}
  1953.         kUnknownEditionFileType                                        = 'edtu';                {unknown file type}
  1954.         {miscellaneous}
  1955.         kFormatLengthUnknown                                        = -1;                    {length of format unknown}
  1956.  
  1957.         {message IDs for Apple events sent by the Edition Manager}
  1958.         sectionEventMsgClass                                        = 'sect';                {Apple events sent by the }
  1959.                                                                 { Edition Manager}
  1960.         sectionReadMsgID                                        = 'read';                {Section Read events}
  1961.         sectionWriteMsgID                                        = 'writ';                {Section Write events}
  1962.         sectionScrollMsgID                                        = 'scrl';                {Section Scroll events}
  1963.         sectionCancelMsgID                                        = 'cncl';                {Section Cancel events}
  1964.  
  1965.         {refCon field when displaying stacked dialog boxes}
  1966.         sfMainDialogRefCon                                        = 'stdf';                {new publisher and }
  1967.                                                                 { new subscriber}
  1968.         sfNewFolderDialogRefCon                                        = 'nfdr';                {new folder}
  1969.         sfReplaceDialogRefCon                                        = 'rplc';                {replace dialog}
  1970.         sfStatWarnDialogRefCon                                        = 'stat';                {warning dialog}
  1971.         sfErrorDialogRefCon                                        = 'err ';                {error dialog}
  1972.         emOptionsDialogRefCon                                        = 'optn';                {options dialog}
  1973.         emCancelSectionDialogRefCon                                        = 'cncl';                {cancel section}
  1974.         emGotoPubErrDialogRefCon                                        = 'gerr';                {locate publisher}
  1975.  
  1976.         {pseudo-item hits for dialogHooks}
  1977.         emHookRedrawPreview                                        = 150;                {for NewPublisher or }
  1978.                                                                 { NewSubscriber dialogs}
  1979.         emHookCancelSection                                        = 160;                {for SectionOptions dialog}
  1980.         emHookGoToPublisher                                        = 161;                {for SectionOptions dialog}
  1981.         emHookGetEditionNow                                        = 162;                {for SectionOptions dialog}
  1982.         emHookSendEditionNow                                        = 162;                {for SectionOptions dialog}
  1983.         emHookManualUpdateMode                                        = 163;                {for SectionOptions dialog}
  1984.         emHookAutoUpdateMode                                        = 164;                {for SectionOptions dialog}
  1985. Data Types
  1986. TYPE TimeStamp                                            = LongInt;                    {seconds since 1904}
  1987.     EditionRefNum                                         = Handle;                     {for use in Edition I/O}
  1988.     UpdateMode                                         = Integer;                    {sumAutomatic, }
  1989.                                                                 { sumManual, } 
  1990.                                                                 { pumOnSave, pumManual}
  1991.     SectionType                                         = SignedByte;                    {stSubscriber or }
  1992.                                                                 { stPublisher} 
  1993.     FormatType                                         = PACKED ARRAY[1..4] OF CHAR; 
  1994.                                                                 {similar to ResType used } 
  1995.                                                                 { by the Scrap  Manager}
  1996.  
  1997.     SectionHandle                                        = ^SectionPtr;
  1998.     SectionPtr                                        = ^SectionRecord;
  1999.     SectionRecord                                         = 
  2000.     RECORD
  2001.         version:                                    SignedByte;                    {always 1 in version 7.0}
  2002.         kind:                                    SectionType;                    {publisher or subscriber}
  2003.         mode:                                    UpdateMode;                    {automatic or manual}
  2004.         mdDate:                                    TimeStamp;                    {last change to section}
  2005.         sectionID:                                    LongInt;                    {application-specific, }
  2006.                                                                 { unique per document}
  2007.         refCon:                                    LongInt;                    {application-specific}
  2008.         alias                                    AliasHandle;                    {handle to alias record}
  2009.  
  2010.         {The following fields are private and are set up by the }
  2011.         { RegisterSection function.}
  2012.  
  2013.         subPart:                                    LongInt;                    {private}
  2014.         nextSection:                                    SectionHandle;                    {private}
  2015.         controlBlock:                                    Handle;                    {private}
  2016.         refNum:                                    EditionRefNum;                    {private}
  2017.     END;
  2018.     EditionContainerSpecPtr =^EditionContainerSpec;
  2019.     EditionContainerSpec
  2020.     RECORD
  2021.         theFile:                                    FSSpec;                    {file containing edition } 
  2022.                                                                 { data}
  2023.         theFileScript:                                     ScriptCode;                    {script code of filename}
  2024.         thePart:                                    LongInt;                    {which part of file, } 
  2025.                                                                 { always kPartsNotUsed}
  2026.         thePartName:                                    Str31;                    {not used in version 7.0}
  2027.         thePartScript:                                     ScriptCode;            ;        {not used in version 7.0}
  2028.     END;
  2029.     FormatsAvailable = ARRAY[0..0] OF
  2030.     RECORD
  2031.         theType:                                    FormatType;                    {format type for an }
  2032.                                                                 { edition}
  2033.         theLength:                                    LongInt;                    {length of edition format }
  2034.                                                                 { type}
  2035.     END;
  2036.     EditionInfoRecord = 
  2037.     RECORD
  2038.         crDate:                                    TimeStamp;                    {date edition container }    
  2039.                                                                 { was created}    
  2040.         mdDate:                                    TimeStamp;                    {date of last change}    
  2041.         fdCreator:                                    OSType;                    {file creator}
  2042.         fdType:                                    OSType;                    {file type}
  2043.         container:                                    EditionContainerSpec;
  2044.                                                                 {the edition}
  2045.     END;
  2046.     NewPublisherReply = 
  2047.     RECORD
  2048.         canceled:                        Boolean;                            {user canceled dialog box} 
  2049.         replacing:                        Boolean;                            {user chose existing } 
  2050.                                                             { filename for an edition}
  2051.         usePart:                        Boolean;                            {always FALSE in version 7.0}
  2052.         preview:                        Handle;                            {handle to 'prvw', 'PICT',}
  2053.                                                             { 'TEXT', or 'snd' data}
  2054.         previewFormat:                        FormatType;                            {type of preview}
  2055.         container:                        EditionContainerSpec;
  2056.                                                             {edition chosen}
  2057.     END;
  2058.     NewSubscriberReply =
  2059.     RECORD
  2060.         canceled:                        Boolean;                            {user canceled dialog box}
  2061.         formatsMask:                        SignedByte;                            {formats required}
  2062.         container:                         EditionContainerSpec;
  2063.                                                             {edition selected}
  2064.     END;
  2065.     SectionOptionsReply =
  2066.     RECORD
  2067.         canceled:                        Boolean;                            {user canceled dialog box}
  2068.         changed:                         Boolean;                            {changed the section }
  2069.                                                             { record}
  2070.         sectionH:                        SectionHandle;                            {handle to the specified }
  2071.                                                             { section record}
  2072.         action:                        ResType;                            {action codes}
  2073.     END;
  2074.     EditionOpenerVerb    = (eoOpen, eoClose, eoOpenNew, eoCloseNew
  2075.                                    eoCanSubscribe); 
  2076.     EditionOpenerParamBlock = 
  2077.     RECORD
  2078.         info:                        EditionInfoRecord;
  2079.                                                             {edition container to }
  2080.                                                             { be subscribed to}
  2081.          sectionH:                        SectionHandle;
  2082.                                                             {publisher or  subscriber}
  2083.                                                             { requesting open}
  2084.         document:                        FSSpecPtr;                            {document passed}
  2085.         fdCreator:                        OSType;                            {Finder creator type}
  2086.         ioRefNum:                        LongInt;                            {reference number}
  2087.         ioProc:                        FormatIOProcPtr;
  2088.                                                             {routine to read formats}
  2089.         success:                        Boolean;                            {reading or writing was }
  2090.                                                             { successful}
  2091.         formatsMask:                        SignedByte;                            {formats required to }
  2092.                                                             { subscribe}
  2093.     END;
  2094.     FormatIOVerb    = (ioHasFormat, ioReadFormat, ioNewFormat,            ioWriteFormat);
  2095.     FormatIOParamBlock = 
  2096.     RECORD
  2097.         ioRefNum:                        LongInt;                            {reference number}
  2098.         format:                        FormatType;                            {edition format type}
  2099.         formatIndex:                        LongInt;                            {opener-specific enumeration }
  2100.                                                             { of formats}
  2101.         offset:                        LongInt;                            {offset into format}
  2102.         buffPtr:                        Ptr;                            {data starts here}
  2103.         buffLen:                        LongInt;                            {length of data}
  2104. END;
  2105. Routines
  2106. Initializing the Edition Manager
  2107. FUNCTION InitEditionPack     : OSErr;
  2108. Creating and Registering a Section
  2109. FUNCTION NewSection    (container: EditionContainerSpec; sectionDocument: FSSpecPtr; kind: SectionType; sectionID: LongInt; initialMode: UpdateMode; VAR sectionH: SectionHandle) : OSErr;
  2110. FUNCTION RegisterSection    (sectionDocument: FSSpec; sectionH:   SectionHandle; VAR aliasWasUpdated: Boolean) : OSErr;
  2111. FUNCTION UnRegisterSection    (sectionH: SectionHandle) : OSErr;
  2112. FUNCTION IsRegisteredSection    (sectionH: SectionHandle) : OSErr;
  2113. FUNCTION AssociateSection    (sectionH: SectionHandle; 
  2114. newSectionDocument: FSSpecPtr) : OSErr;
  2115. Creating and Deleting an Edition Container
  2116. FUNCTION CreateEditionContainerFile    
  2117. (editionFile: FSSpec; fdCreator: OSType;  editionFileNameScript: ScriptCode) : OSErr;
  2118. FUNCTION DeleteEditionContainerFile    
  2119. (editionFile: FSSpec) : OSErr;
  2120. Setting and Locating a Format Mark
  2121. FUNCTION SetEditionFormatMark    (whichEdition: EditionRefNum; 
  2122.  whichFormat: FormatType; 
  2123.  setMarkTo: LongInt) : OSErr;
  2124. FUNCTION GetEditionFormatMark        (whichEdition: EditionRefNum; 
  2125.  whichFormat: FormatType; 
  2126.  VAR currentMark: LongInt) : OSErr; 
  2127. Reading in Edition Data
  2128. FUNCTION OpenEdition    (subscriberSectionH: SectionHandle; VAR refNum: EditionRefNum) : OSErr;
  2129. FUNCTION EditionHasFormat    (whichEdition: EditionRefNum; 
  2130. whichFormat: FormatType; 
  2131. VAR formatSize: Size) : OSErr; 
  2132. FUNCTION ReadEdition    (whichEdition: EditionRefNum; 
  2133. whichFormat: FormatType; buffPtr: UNIV Ptr; VAR buffLen: Size) : OSErr;
  2134. Writing out Edition Data
  2135. FUNCTION OpenNewEdition    (publisherSectionH: SectionHandle; 
  2136. fdCreator: OSType; 
  2137. publisherSectionDocument: FSSpecPtr; 
  2138. VAR refNum: EditionRefNum) : OSErr;
  2139. FUNCTION WriteEdition    (whichEdition: EditionRefNum; 
  2140. whichFormat: FormatType; buffPtr: UNIV Ptr; buffLen: Size) : OSErr;
  2141. Closing an Edition After Reading or Writing
  2142. FUNCTION CloseEdition    (whichEdition: EditionRefNum; 
  2143. successful: Boolean) : OSErr;
  2144. Displaying Dialog Boxes
  2145. FUNCTION GetLastEditionContainerUsed    
  2146. (VAR container: EditionContainerSpec) : OSErr;
  2147. FUNCTION NewSubscriberDialog                        
  2148. (VAR reply: NewSubscriberReply) : OSErr;
  2149. FUNCTION NewPublisherDialog     (VAR reply: NewPublisherReply) : OSErr;
  2150. FUNCTION SectionOptionsDialog    
  2151. (VAR reply: SectionOptionsReply) : OSErr;
  2152. FUNCTION NewSubscriberExpDialog    
  2153. (VAR reply: NewSubscriberReply; where: Point; expansionDITLresID: Integer; 
  2154. dlgHook: ExpDlgHookProcPtr; 
  2155. filterProc: ExpModalFilterProcPtr; yourDataPtr: UNIV Ptr) : OSErr;
  2156. FUNCTION NewPublisherExpDialog    
  2157. (VAR reply: NewPublisherReply; where: Point; expansionDITLresID: Integer; 
  2158. dlgHook: ExpDlgHookProcPtr; 
  2159. filterProc: ExpModalFilterProcPtr; yourDataPtr: UNIV Ptr) : OSErr;
  2160. FUNCTION SectionOptionsExpDialog    
  2161. (VAR reply: SectionOptionsReply; where: Point; expansionDITLresID: Integer; 
  2162. dlgHook: ExpDlgHookProcPtr; 
  2163. filterProc: ExpModalFilterProcPtr; yourDataPtr: UNIV Ptr) : OSErr;
  2164. Locating a Publisher and Edition From a Subscriber
  2165. FUNCTION GetEditionInfo    (sectionH: SectionHandle; 
  2166. VAR editionInfo: EditionInfoRecord) : OSErr;
  2167. FUNCTION GoToPublisherSection    (container: EditionContainerSpec) : OSErr;
  2168. Edition Container Formats
  2169. FUNCTION GetStandardFormats    (container: EditionContainerSpec; 
  2170. VAR previewFormat: FormatType; 
  2171. preview, publisherAlias, 
  2172. formats: Handle) : OSErr;
  2173. Reading and Writing Non-Edition files
  2174. FUNCTION GetEditionOpenerProc    (VAR opener: EditionOpenerProcPtr) : OSErr;
  2175. FUNCTION SetEditionOpenerProc    (opener: EditionOpenerProcPtr) : OSErr;
  2176. FUNCTION CallEditionOpenerProc    
  2177. (selector: EditionOpenerVerb; 
  2178.  VAR PB: EditionOpenerParamBlock; 
  2179.  routine: EditionOpenerProcPtr) : OSErr;
  2180. FUNCTION CallFormatIOProc             (selector: FormatIOVerb; 
  2181.  VAR PB: FormatIOParamBlock; 
  2182.  routine: FormatIOProcPtr) : OSErr;
  2183. Application-Defined Routines
  2184. FUNCTION MyExpDlgHook    (itemOffset: Integer; itemHit: Integer; 
  2185. theDialog: DialogPtr; 
  2186. yourDataPtr: Ptr) : Integer;
  2187. FUNCTION MyExpModalFilter    (theDialog: DialogPtr; 
  2188. VAR theEvent: EventRecord; 
  2189. itemOffset: Integer; VAR itemHit: Integer; yourDataPtr: Ptr) : Boolean;
  2190. FUNCTION MyOpener    (selector: EditionOpenerVerb; 
  2191. VAR PB: EditionOpenerParamBlock) : OSErr;
  2192. FUNCTION MyIO    (selector: FormatIOVerb; 
  2193. VAR PB: FormatIOParamBlock) : OSErr;
  2194. Result Codes
  2195. noErr    0    No error
  2196. abortErr    –27    Publisher has written a new edition
  2197. eofErr    –39    No additional data in the format
  2198. fnfErr    –43    Edition container not found
  2199. flLckedErr    –45    Publisher writing to an edition
  2200. fBsyErr    –47    Section doing I/O
  2201. rfNumErr    –51    Bad edition reference number
  2202. permErr    –54    Not a subscriber
  2203. wrPermErr    –61    Not a publisher
  2204. noTypeErr    –102    Format not available
  2205. memFullErr    –108    Could not load package
  2206. userCanceledErr    –128    User chose Cancel from dialog box
  2207. editionMgrInitErr    –450    Manager not initialized or could not load package
  2208. badSectionErr    –451    Not a valid section type
  2209. notRegisteredSectionErr    –452    Not registered
  2210. badSubPartErr    –454    Bad edition container spec or invalid edition container
  2211. multiplePublisherWrn    –460    Already is a publisher
  2212. containerNotFoundWrn    –461    Alias was not resolved
  2213. notThePublisherWrn    –463    Not the publisher
  2214. The Apple Event Manager
  2215. Introduction to Apple Events2-6
  2216. Apple Events and Apple Event Objects2-9
  2217. Components of Apple Events2-12
  2218. Data Structures Within Apple Events2-17
  2219. Descriptor Records2-17
  2220. Descriptor Lists2-22
  2221. Responding to Apple Events2-25
  2222. Requesting Services Through Apple Events2-33
  2223. Working With Object Specifier Records2-38
  2224. The Classification of Apple Event Objects2-45
  2225. Object Classes2-45
  2226. Properties and Elements2-48
  2227. Resolving Object Specifier Records2-53
  2228. About the Apple Event Manager2-57
  2229. Using the Apple Event Manager2-59
  2230. Accepting an Apple Event2-60
  2231. Installing Entries in the Apple Event Dispatch Tables2-63
  2232. Installing Entries in the Object Accessor Dispatch Tables2-66
  2233. Installing Object Accessor Functions That Find Apple Event Objects2-68
  2234. Installing Object Accessor Functions That Find Properties2-71
  2235. Handling the Required Apple Events2-72
  2236. Required Apple Events2-72
  2237. Handling the Open Application Event2-75
  2238. Handling the Open Documents Event2-76
  2239. Handling the Print Documents Event2-78
  2240. Handling the Quit Application Event2-80
  2241. Handling Apple Events Sent by the Edition Manager2-81
  2242. Handling the Create Publisher Event2-82
  2243. Getting Data Out of an Apple Event2-85
  2244. Getting Data Out of an Apple Event Parameter2-87
  2245. Getting Data Out of an Attribute2-89
  2246. Getting Data Out of a Descriptor List2-91
  2247. Writing Apple Event Handlers2-93
  2248. Replying to an Apple Event2-96
  2249. Disposing of Apple Event Data Structures2-98
  2250. Interacting With the User2-100
  2251. Setting the Client Application’s User Interaction Preferences2-100
  2252. Setting the Server Application’s User Interaction Preferences2-102
  2253. Requesting User Interaction2-103
  2254. Creating an Apple Event2-110
  2255. Adding Parameters to an Apple Event2-111
  2256. Specifying Optional Parameters for an Apple Event2-112
  2257. Specifying a Target Address2-116
  2258. Creating an Object Specifier Record2-118
  2259. Creating a Simple Object Specifier Record2-123
  2260. Specifying the Container Hierarchy2-126
  2261. Creating a Complex Object Specifier Record2-128
  2262. Sending an Apple Event2-143
  2263. Dealing With Timeouts2-149
  2264. Writing an Idle Function2-150
  2265. Writing a Reply Filter Function2-152
  2266. Writing and Installing Coercion Handlers2-153
  2267. Writing Object Accessor Functions2-157
  2268. Writing Object Accessor Functions That Find Apple Event Objects2-159
  2269. Writing Object Accessor Functions That Find Properties2-167
  2270. Defining Tokens2-169
  2271. Supporting Whose Descriptor Records2-170
  2272. Writing Object Callback Functions2-173
  2273. Writing an Object-Counting Function2-175
  2274. Writing an Object Comparison Function2-177
  2275. Writing Marking Callback Functions2-179
  2276. Reference to the Apple Event Manager2-182
  2277. Data Structures2-182
  2278. Apple Event Manager Routines2-183
  2279. Creating and Managing the Apple Event Dispatch Tables2-183
  2280. Initializing the Object Support Library2-188
  2281. Setting Object Accessor Functions and Object Callback Functions2-189
  2282. Getting, Calling, and Removing Object Accessor Functions2-192
  2283. Dispatching Apple Events2-196
  2284. Getting Data or Descriptor Records from Apple Event Parameters and Attributes2-197
  2285. Counting the Items in Descriptor Lists2-203
  2286. Getting Items From Descriptor Lists2-203
  2287. Getting Data and Keyword-Specified Descriptor Records From AE Records2-207
  2288. Resolving Object Specifier Records2-209
  2289. Requesting User Interaction2-211
  2290. Requesting More Time to Respond to Apple Events2-214
  2291. Suspending and Resuming Apple Event Handling2-215
  2292. Creating Apple Events2-218
  2293. Creating and Duplicating Descriptor Records2-219
  2294. Creating Descriptor Lists and AE Records2-221
  2295. Creating Object Specifier Records2-222
  2296. Adding Items to Descriptor Lists2-228
  2297. Adding Data and Descriptor Records to AE Records2-231
  2298. Adding Parameters and Attributes to Apple Events2-232
  2299. Sending Apple Events2-237
  2300. Getting the Sizes and Descriptor Types of Descriptor Records2-240
  2301. Deleting Descriptor Records2-243
  2302. Deallocating Memory for Descriptor Records2-244
  2303. Deallocating Memory for Tokens2-245
  2304. Coercing Descriptor Types2-246
  2305. Creating and Managing the Coercion Handler Dispatch Tables2-247
  2306. Creating and Managing the Special Handler Dispatch Tables2-251
  2307. Application-Defined Functions2-254
  2308. Object Accessor Functions2-255
  2309. Object Callback Functions2-256
  2310. Summary of the Apple Event Manager2-265
  2311. 2The Apple Event Manager
  2312. This chapter describes Apple events, Apple event objects, and the data structures and routines that your application can use to construct, send, receive, and process Apple events.
  2313. As explained in the chapter “The Event Manager” in Inside Macintosh: Macintosh Toolbox, the Event Manager lets applications communicate with each other by sending high-level events. Using Event Manager routines, your application can create and process its own high-level events. 
  2314. However, effective interapplication communication requires that applications agree on a standard set of conventions—a common vocabulary. To provide such a standard, Apple Computer, Inc., has defined a protocol called the Apple Event Interprocess Messaging Protocol (AEIMP). High-level events that conform to this protocol are called Apple events. You can ensure effective communication between your application and other Macintosh applications by using this protocol.
  2315. The vocabulary of publicly available Apple events is defined in the Apple Event Registry: Standard Suites, which defines the standard Apple events that developers and Apple have developed for use by all applications. The Apple Event Developers Association (AEDA) acts as a clearinghouse for information about Apple events and maintains the Apple Event Registry: Standard Suites.  
  2316. The main requirement for effective communication between applications is some method of referring to menu commands, windows, data (such as words or shapes), and other items within any application or its documents. The Apple Event Registry: Standard Suites makes this possible by defining classes of Apple event objects, which are distinct items in an application or any of its documents that can be described in an Apple event. Apple event objects are often, but not always, items that a user can differentiate and manipulate within an application, such as words, paragraphs, shapes, windows, menu commands, or style formats. 
  2317. Most of the standard Apple events in the Apple Event Registry: Standard Suites require your application to support specific Apple event object classes. Support for the standard Apple events, including Apple event objects, allows your application to exchange services and information with any other application that supports the same Apple events. In addition, support for the standard Apple events ensures that you can make your application scriptable—that is, capable of responding to scripts written in a scripting language such as AppleScript, the system-wide scripting language currently being developed by Apple.
  2318. The Apple Event Manager is available only in system software version 7.0 or later. To determine whether the Apple Event Manager is available, use the Gestalt function. In order to support Apple event objects, you must also link the current version of the Object Support Library to your application when you compile it.
  2319. The interapplication communications architecture of system software version 7.0 currently consists of three main components: the Event Manager, the Program-to-Program Communications (PPC) Toolbox, and the Apple Event Manager. See the chapter “Introduction to Collaborative Computing” in this book for an overview of the relationships among these components.
  2320. To use this chapter, you should also be familiar with the chapters “The Event Manager” in Inside Macintosh: Macintosh Toolbox and “The Process Manager” in Inside Macintosh: Operating System. To allow your application to send Apple events to applications on other computers, you may wish to use the PPCBrowser function, which is described in the chapter “Program-to-Program Communications Toolbox” in this book.
  2321. While the Apple events used by the Edition Manager are discussed in this chapter, you must refer to the chapter “The Edition Manager” in this book for a full discussion of how to implement the Edition Manager’s publish and subscribe features.
  2322. This chapter begins with an introduction that explains important concepts you need to understand before you begin to implement Apple events in your own application. Following the introduction, a section called “About the Apple Event Manager” summarizes the steps you neeed to take in order to support Apple events in your application.
  2323. The remainder of the chapter describes in detail how to use the Apple Event Manager to
  2324. n    accept an Apple event
  2325. n    install Apple event handlers and object accessor functions in the appropriate dispatch tables
  2326. n    handle the required Apple events and the Apple events sent by the Edition Manager
  2327. n    extract data from an Apple event
  2328. n    write Apple event handlers and related functions
  2329. n    interact with the user when necessary
  2330. n    create an Apple event
  2331. n    create an object specifier record
  2332. n    send an Apple event
  2333. n    write object accessor functions that can locate Apple event objects in your application
  2334. Introduction to Apple Events
  2335. An Apple event is a high-level event that conforms to the Apple Event Interprocess Messaging Protocol. The Apple Event Manager uses the services of the Event Manager to send Apple events between applications on the same computer or between applications on remote computers. 
  2336. Applications typically use Apple events to request services and information from other applications or to provide services and information in response to such requests. For example, the Open Documents event requests that your application open specified documents. When your application supports this Apple event, it should respond by opening those documents in the manner that your application normally opens documents.    
  2337. Communication between two applications that support Apple events is initiated by a client application, which sends an Apple event to request a service or information. For example, a client application might request services such as printing specific files, spell-checking a list of words, or performing a numerical calculation; or it might request information, such as one customer’s address or a list of names and addresses for all customers living in Ohio. The application providing the service or the requested information is called a server application. The client and server applications can reside on the same local computer or on remote computers connected to a network. 
  2338. Figure 2-1 shows a common Apple event, the Open Documents event. The Finder application is the client; it requests that the SurfWriter application open the documents named Dec. Invoice and Nov. Invoice. The SurfWriter application responds to the Finder’s request by opening windows containing the specified documents.
  2339. An Open Documents event
  2340. The Finder is considered the client application for the Open Documents event shown in Figure 2-1 because the Finder initiates the request for a service. The Finder can also be considered the source application for the same Open Documents event. A source application for an Apple event is one that sends an Apple event to another application or to itself. Similarly, the SurfWriter application can be described as either the server application or the target application for the Open Documents event shown in Figure 2-1. A target application for an Apple event is the one addressed to receive the Apple event. The terms client application and source application are not always synonymous, nor are the terms server application and target application. Typically, an Apple event client application sends an Apple event requesting a service to an Apple event server application; in this case, the server application is the target application for the Apple event. A server application may send back a different Apple event as a response—in which case, the client application becomes the target application for the responding Apple event.  
  2341. In order to perform the requested service—that is, to open the specified documents—the SurfWriter application shown in Figure 2-1 must be able to extract information from the Apple event that tells what kind of event it is (the Open Documents event) and which documents to open (Dec. Invoice and Nov. Invoice.) To identify Apple events and respond appropriately, every application can rely on a small vocabulary of standard Apple events that developers and Apple have established for all applications to use. 
  2342. The standard Apple events  are defined in the Apple Event Registry: Standard Suites. The standard suites, or groups of related Apple events that are usually implemented together, include the following: 
  2343. n    The Required suite consists of the four Apple events that the Finder sends to applications. These events are called Open Documents, Open Application, Print Documents, and Quit Application. The Finder uses the required events as part of the mechanisms in system software version 7.0 for launching and terminating applications. Your application must support the required Apple events as described in “Handling the Required Apple Events,” which begins on page 2-72, in order to be 7.0-friendly.
  2344. n    The Core suite consists of the basic Apple events that nearly all applications use to communicate, including Get Data, Move, Delete Element, Save, and Undo. You should support all the Apple events in the Core suite that make sense for your application. 
  2345. n    Functional-area suites consist of groups of Apple events that support related functional areas, and include the Text Suite, the QuickDraw Graphics suite, and the Database suite. You can decide which functional area suites to support according to the features provided by your application. For example, most word-processing applications should support the Text suite, and most graphics applciations should support the QuickDraw Graphics suite.
  2346. If necessary, you can extend the definitions of the standard Apple events to match specific capabilities of your application. You can also define your own custom Apple events; however, before deciding whether you need to define custom Apple events, you should check with the Apple Event Developers Association (AEDA) to find out whether Apple events that already exist or are under development can be adapted to the needs your application. 
  2347. Custom Apple events require other applications to support them explicitly. If all applications relied solely on custom Apple events for interapplication communication, each application would have to support all other applications’ custom Apple events. Instead of creating custom Apple events, it is usually preferable use the standard Apple events and extend their definitions as necessary for your application.
  2348. By supporting the standard Apple events in your application, you can ensure that your application can communicate effectively with other applications that also support them. Instead of supporting many different custom events for a limited number of applications, you can support a small number of standard Apple events that can be used by any number of applications. Supporting the standard Apple events also ensures that you can make your application scriptable, or capable of responding to instructions written in a scripting language such as AppleScript, the system-wide scripting language currently being developed by Apple.
  2349. The remainder of this introduction describes how applications can use Apple events and Apple event objects to request or provide services, what Apple events contain, the data structures from which they are constructed, and other important concepts you need to understand before you begin implementing the standard Apple events in your application. However, if you intend to start by providing support only for the Required suite of Apple events, you can skip the last three sections of this introduction (“Working With Object Specifier Records,” “The Classification of Apple Event Objects,” and “Resolving Object Specifier Records”) until you are ready to begin implementing the Core suite of Apple events. 
  2350. For more information about the steps you need to take to support Apple events in your application, see “About the Apple Event Manager,” which begins on page 2-57.
  2351. The next section, “Apple Events and Apple Event Objects,” provides an overview of the way Apple events can describe menu commands, data, and other items within another application or its documents. You need to understand the concepts described in the next section before you decide which of the standard Apple event suites you want to begin implementing.
  2352. Apple Events and Apple Event Objects
  2353. Figure 2-1 on page 2-7 illustrates how a client application can send an Open Documents event to a server application in order to request that the server application open specific documents. The server application only needs to identify the Apple event and open the specified documents. However, effective communication between applications requires a method of referring to menu commands, windows, data (such as words or shapes), and other items within a target application or its documents. The Apple Event Manager allows any application to construct and interpret references to such items by means of a standard classification scheme for Apple event objects.
  2354. An Apple event object is a distinct item in a target application or any of its documents that can be described within an Apple event. Apple event objects can be anything that an application can locate on the basis of such a description, including items that a user can differentiate and manipulate within an application, such as words, paragraphs, shapes, windows, menu commands, or style formats. All the standard suites of Apple events except for the Required suite include definitions of the classes of Apple event objects upon which the Apple events in the suite can act. In order to support Apple events other than the Required suite and those sent by the Edition Manager, your application must also support the corresponding Apple event objects. 
  2355. The definition for each Apple event object class in the Apple Event Registry: Standard Suites determines only how that kind of Apple event object should be described within an Apple event, not how it should be represented internally by an individual application. You do not have to write your application in an object-oriented programming language in order to support Apple event objects. Instead, you need to organize your application so that it will be able to interpret a request for a specific Apple event object correctly.
  2356. Figure 2-2 shows a common Apple event, the Get Data event from the Core suite. In this example, the BeachCharter application is the client application; it requests data contained in a specific table in a SurfWriter document. To make sure it receives the data it wants, the BeachCharter application must include a description of the data as part of the Get Data event it sends to SurfWriter. This description identifies the requested data as a particular kind of Apple event object called a table, which is named “Summary of Sales, 1991” and is located in a document named “Sales Report.” 
  2357. The SurfWriter application responds to the request by locating the specified table and sending a reply Apple event to the BeachCharter application. The reply Apple event returns the requested data to the BeachCharter application in the form requested by the Get Data event. When it receives the reply Apple event, the BeachCharter application displays the data in its active window in the form of a pie chart. (A client application can display the data returned by a reply Apple event in any way that is appropriate.) 
  2358. The BeachWriter application shown in Figure 2-2 must be able to construct a standard Get Data Apple event that includes a description of the requested table, and the SurfWriter application must be able to extract information from the Get Data event that tells what kind of event it is and which data to get. The Apple Event Manager includes routines that allow your application both to construct Apple events and to extract information from them. The rules for constructing and interpreting different kinds of Apple events are described in the Apple Event Registry: Standard Suites. Your application must follow these rules when it constructs or interprets any standard Apple event that it supports. After your application has extracted information from an Apple event, it should perform the action associated with that event, including locating any specified Apple event objects.
  2359. A Get Data event 
  2360. Apple events often correspond to the actions performed by menu commands. For example, the Quit, Delete, Undo, and Close events all perform the same actions as their menu equivalents. By supporting Apple events and related Apple event objects that correspond to actions and distinct items available to a user from within your application, you can allow a scripting language such as AppleScript to intercede comfortably between your applicaton’s visual interface—its menus, dialog boxes, and other visual means of interacting with the user—and its internal organization. This means that a script can perform any action or series of actions within your application that a user might normally perform, without reference to low-level events such as mouse clicks and menu selections. 
  2361. A script is a series of statements in a scripting language that send Apple events to one or more applications in order to execute a series of tasks. Scripts are especially useful for conditional or repetitive operations that require precise execution of a sequence of tasks, and for tasks that involve several machines across a network. For example, a script might generate the Apple events that correspond to the instructions “Open application, open Daily Stock Report document, choose Get Latest Quotes menu command, save document, print document, and quit application.” The ability to control your application with scripts is the major benefit that users will receive as a result of your support for Core suite and any functional-area suites that are appropriate for your application. 
  2362. Components of Apple Events
  2363. An Apple event consists of attributes (which identify the Apple event and denote its task) and, often, parameters (which contain data to be used by the target application). Applications use the Apple Event Manager to create Apple events. Using arguments you pass to the AECreateAppleEvent function and to other Apple Event Manager routines, the Apple Event Manager constructs the data structures that make up the attributes and parameters of an Apple event. Applications must use the Apple Event Manager’s AESend function to transmit the Apple event. After receiving an Apple event, applications must use Apple Event Manager routines to extract the event’s attributes and parameters.
  2364. Attributes are a fundamental component of Apple events. Apple event attributes are records that identify the event class, event ID, target application, and other characteristic of an Apple event. Taken together, the attributes of an Apple event denote the task to be performed on any data specified in the Apple event’s parameters. You must use Apple Event Manager routines to add attributes to an Apple event. After the attributes are part of the Apple event, you must use Apple Event Manager routines to extract and examine them. 
  2365. An Apple event parameter is a record containing data that the target application uses. Unlike Apple event attributes (which contain information that can be used by both the Apple Event Manager and the target application), Apple event parameters contain data used only by the target application. For example, an attribute like the event ID is used by the Apple Event Manager to call a handler from the server application’s Apple event dispatch table, and the server application must have a handler to process the event identified by that attribute. By comparison, the list of documents contained in a parameter to an Open Documents event is used only by the server application. As with attributes, you must use Apple Event Manager routines to add parameters to an Apple event, and after parameters are attached to an Apple event, you must use Apple Event Manager routines to extract and examine them.
  2366. As explained in the preceding section, “Apple Events and Apple Event Objects,” your application must make use of Apple Event Manager routines to construct Apple events and extract information from them according to the conventions described in the Apple Event Registry: Standard Suites.
  2367. Note that Apple event parameters are different from the parameters of Apple Event Manager functions. Apple event parameters are records private to the Apple Event Manager; function parameters are arguments you pass to the function or that the function returns to you. You typically specify the Apple event parameters (as well as the attributes) in parameters to Apple Event Manager functions. For example, the AEGetParamPtr function uses a buffer to return the data contained in an Apple event parameter. You specify which Apple event parameter in one of the parameters of the AEGetParamPtr function.
  2368. Apple events are identified by their event class and event ID attributes. The event class is the attribute that identifies a group of related Apple events. The event class appears in the message field of the event record for an Apple event. For example, the four required Apple events have the value 'aevt' in the message fields of their event records. The value 'aevt' can also be represented by the kCoreEventClass constant. Several event classes are shown here:
  2369. Event class        Value    Description
  2370. kCoreEventClass        'aevt'    A required Apple event
  2371. kAECoreSuite        'core'    A Core Apple event
  2372. kAEFinderEvents        'FNDR'    An event that the Finder accepts
  2373. kSectionEventMsgClass        \qsect'    An event sent by the Edition Manager
  2374. The event ID is the attribute that identifies the particular Apple event within its event class. In conjunction with the event class, the event ID uniquely identifies the Apple event and communicates what action the Apple event should perform. (The event IDs appear in the where field of the event record for an Apple event. For more information about event records, see the chapter ‘The Event Manager” in Inside Macintosh: Macintosh Toolbox.) For example, the event ID of an Open Documents event has the value 'odoc' (which can also be represented by the kAEOpenDocuments constant). The kCoreEventClass constant in combination with the kAEOpenDocuments constant identifies the Open Documents event to the Apple Event Manager.
  2375. Here are the event IDs for the four required Apple events:
  2376. Event ID        Value    Description
  2377. kAEOpenApplication         'oapp'    Perform tasks required when a user
  2378.             opens your application without 
  2379.             opening or printing any documents
  2380. kAEOpenDocuments        'odoc'    Open documents
  2381. kAEPrintDocuments        'pdoc'    Print documents
  2382. kAEQuitApplication        'quit'    Quit your application
  2383. In addition to the event class and event ID attributes, every Apple event must include an attribute that specifies the target application’s address. As described in the previous section, “Apple Events and Apple Event Objects,” the target application is the one addressed to receive the Apple event. Your application can send an Apple event to itself or to another application (on the same computer or on a remote computer connected to the network).
  2384. As with attributes, there are various types of Apple event parameters. A direct parameter usually contains the data to be acted upon by the server application. For example, the direct parameter of the Print Documents event contains a list of documents. A direct parameter is usually a required parameter—a parameter that is required in order to carry out the task denoted by the Apple event. The Apple Event Registry: Standard Suites specifies which parameters are normally required for the standard Apple events. Some Apple events also take additional parameters, which the server application uses in addition to the data specified in the direct parameter. For example, an Apple event for arithmetic operations may include additional parameters that specify operands in an equation. Additional parameters may be required or optional.
  2385. The Apple Event Registry: Standard Suites describes all parameters as either required or optional. An optional parameter is a supplemental Apple Event parameter that also can be used to specify data to the server application. Optional parameters need not be included in an Apple event; default values for optional parameters are part of the event definition. The server application that handles the event must supply default values if the optional parameters are omitted.  
  2386. The source application is responsible for identifying which Apple event parameters the server should treat as optional. This means that, for a specific event, the source application can force the target application to treat parameters that are listed as optional parameters in the Apple Event Registry: Standard Suites as if they were required, and vice versa. For more information about optional parameters, see “Specifying Optional Parameters for an Apple Event” on page 2-112.<36pt\>\x12 <8bat\>u
  2387. The next section, “Data Structures Within Apple Events,” describes the data structures the Apple Event Manager uses for Apple event attributes and parameters. The rest of this section provides an overview of the role attributes and parameters play in the Open Documents and Get Data events illustrated by Figure 2-1 and Figure 2-2.
  2388. Figure 2-3 shows in greater detail the components of the Open Documents event that was introduced in Figure 2-1.
  2389. Major components of an Open Documents event
  2390. To process the information contained in the Open Documents event, the SurfWriter application uses the AEProcessAppleEvent function. The AEProcessAppleEvent function provides an easy way for your application to extract the event class and event ID of any Apple event from the corresponding attributes and call the code in your program that handles the Apple event.
  2391. The definition of a given Apple event in the Apple Event Registry: Standard Suites determines how the source application organizes the data in the Apple event’s parameters and how the target application interprets that data. The data in an Apple event parameter may be a string of text, a long integer, a Boolean value, an alias record, any of various other standard data types, or a description of an Apple event object. The code in your program that handles each Apple event you support interprets the data in an Apple event parameter differently depending on the kind of Apple event—that is, the event class and event ID.
  2392. Apple events can use standard data types, such as strings of text, long integers, and Boolean values, to contain the corresponding data in Apple event parameters. For example, the Get Data event can contain an optional parameter, specified as four-character string, that specifies the form in which the data requested by the client application should be returned. This optional parameter always consists of a four-character code. Apple events can also use special data types defined by the Apple Event Manager
  2393. Apple event parameters often contain descriptions of Apple event objects. An Apple event object is a distinct item in a target application or any of its documents that can be described precisely within an Apple event sent by a source application. These descriptions of Apple event objects make use of a standard classification scheme that provides a convenient method of referring to Apple event objects in other applications or their documents. The classification scheme used to describe Apple event objects is summarized in “The Classification of Apple Event Objects,” which begins on page 2-45. For information about the way specific kinds of Apple event objects fit into this scheme, see the Apple Event Registry: Standard Suites.
  2394. Apple event parameters can contain descriptions of one or more Apple event objects, but Apple event parameters never contain the Apple event objects themselves. Apple event objects can be anything that an application can locate on the basis of such a description, including items that a user can differentiate and manipulate, such as words, paragraphs, shapes, windows, menu commands, or style formats. For example, every Get Data event includes a required parameter that identifies the Apple event object whose data the client application is requesting, such as a word, a line, a paragraph, a related group of paragraphs, or the entire document. Thus one application can send a Get Data event to another application, requesting that the other application return one paragraph of a document, the first and last paragraphs of a document, all pictures in the document, all paragraphs containing the word “sales,” or pages 10 through 12 of the document. 
  2395. Figure 2-4 shows in greater detail the components of the Get Data event that was introduced in Figure 2-2. The BeachCharter application sends a Get Data event to the SurfWriter application. The direct parameter for the Get Data event identifies the Apple event object requested as a table with the caption “Summary of Sales, 1991” in the document “Sales Report.” Both the table and the document are Apple event objects. The description of an Apple event object must include a description of where the Apple event object is located. The requested Apple event object is usually located within another Apple event object.
  2396. Major components of a Get Data event
  2397. To process the information contained in the Get Data event, the SurfWriter application calls the AEProcessAppleEvent function, which directs the Apple Event Manager to call the code in the SurfWriter application that handles the Get Data Apple event. The SurfWriter application responds to the Get Data event by resolving the description of the Apple event object—that is, by using the AEResolve function, other Apple Event Manager routines, and its own application-defined routines to locate the table named “Summary of Sales, 1991.” When the SurfWriter application locates the table, it sends a reply event containing the table’s data to the BeachCharter application. The BeachCharter application responds to the reply Apple event by displaying the data in its active window.  
  2398. Data Structures Within Apple Events
  2399. An application must use Apple Event Manager functions to create, send, and process an Apple event. The Apple Event Manager constructs its own internal data structures to contain the information in an Apple event. To gain access to this data, the target application must almost always use Apple Event Manager functions. Neither the sender nor the receiver of an Apple event can directly manipulate data after it has been added to an Apple event record; each must rely on Apple Event Manager functions to do so. This section describes the data structures that the Apple Event Manager uses to create, send, and process Apple events.
  2400. The first data structure described in this section is the descriptor record, a data structure of type AEDesc that the Apple Event Manager uses for many different purposes. In some cases it is convenient to refer to descriptor records by data type names that indicate their contents; thus, the Apple Event Manager also defines data structures such as type AEAddressDesc, AEDescList, and AERecord, which are descriptor records used to hold addresses, lists of of other descriptor records, and Apple event parameters, respectively. These and most of the other data structures described in this section are formally defined as data structures of type AEDesc; they differ only in the purposes for which they are used. 
  2401. Descriptor Records
  2402. Descriptor records are the fundamental structures from which Apple event attributes and parameters are constructed. A descriptor record is a data structure of type AEDesc; it consists of a handle to data and a descriptor type that identifies the type of the data referred to by the handle.
  2403. TYPE AEDesc = 
  2404.     RECORD                                            {descriptor record}
  2405.         descriptorType:                        DescType;                {type of data being passed}
  2406.         dataHandle:                         Handle                {handle to data being passed}
  2407.     END;
  2408. It is sometimes possible to retrieve the data associated with a handle in a descriptor record by dereferencing the handle twice. This will only work if the descriptor record is not part of an Apple event. After a descriptor record has been added to an Apple event, you must use Apple Event Manager routines to extract its data.
  2409. The descriptor type is a structure of type DescType, which in turn is of data type ResType—that is, a four-character string. Constants are usually used in place of these four-character strings when referring to descriptor types. Descriptor types represent various data types. Here is a list of the major descriptor type constants, their values, and the types of data they represent.
  2410. Descriptor type        Value    Description
  2411. typeBoolean        'bool'    Boolean value
  2412. typeChar        'TEXT'    Unterminated string
  2413. typeLongIntege    r    'long'    32-bit integer
  2414. typeShortInteger        'shor'    16-bit integer
  2415. typeLongFloat        'doub'    SANE<Superscript\>\xa8  double
  2416. typeShortFloat        'sing'    SANE single
  2417. typeExtended        'exte'    SANE extended
  2418. typeComp        'comp'    SANE comp
  2419. typeMagnitude        'magn'    Unsigned 32-bit integer
  2420. typeAEList        'list'    List of descriptor records
  2421. typeAERecord        'reco'    List of keyword-specified
  2422.             descriptor records
  2423. typeAppleEvent        'aevt'    Apple event record
  2424. typeTrue        'true'    TRUE Boolean value
  2425. typeFalse        'fals'    FALSE Boolean value
  2426. typeAlias        'alis'    Alias record
  2427. typeEnumerated        'enum'    Enumerated data
  2428. typeType        'type'    Four-character code for
  2429.                 event class or event ID
  2430. typeAppParameter    s    'appa'    Process Manager launch
  2431.                 parameters
  2432. typeProperty        'prop'    Apple event property
  2433. typeFSS        'fss '    File system specification
  2434. typeKeyword        'keyw'    Apple event keyword
  2435. typeSectionH        'sect'    Handle to a section record
  2436. typeWildCard        '****'    Matches any type
  2437. typeApplSignature        'sign'    Application signature
  2438. typeSessionID        'ssid'    Session reference number
  2439. typeTargetID        'targ'    Target ID record
  2440. typeProcessSerialNumbe    r    'psn '    Process serial number
  2441. typeNull        'null'    NULL or nonexistent data
  2442. typeObjectSpecifier        'obj '    Object specifier record
  2443. typeObjectBeingExamined     'exmn'        Part of object specifier record
  2444. typeCurrentContainer        'ccnt'                Part of object specifier record
  2445. typeRelativeDescriptor        'rel '                Part of object specifier record
  2446. typeAbsoluteOrdinal         'abso'    Part of object specifier record
  2447. typeIndexDescriptor        'inde'                Part of object specifier record
  2448. Descriptor type        Value    Description
  2449. typeRangeDescriptor        'rang'    Part of object specifier record
  2450. typeLogicalDescriptor        'logi'    Part of object specifier record
  2451. typeCompDescriptor        'cmpd'    Part of object specifier record
  2452. The constant typeObjectSpecifier and the constants that follow it in the preceding list designate special descriptor types used to define object specifier records, which are the data structures used for Apple event parameters that contain descriptions of Apple event objects. See “Working With Object Specifier Records” on page 2-38 for more information about object specifier records.
  2453. Figure 2-5 illustrates the logical arrangement of a descriptor record with a descriptor type of typeChar, which specifies that the data in the descriptor record is an unterminated string. The string in this descriptor record consists of the text “Summary of Sales, 1991.”
  2454. A descriptor record that contains an unterminated string.
  2455. Figure 2-6 illustrates the logical arrangement of a descriptor record with a descriptor type of typeType, which specifies that the data in the descriptor record must consist of a four-character code. The data in this descriptor record is specified by the constant kCoreEventClass, whose value is 'aevt'. As you will see by the end of this section, this descriptor record can be used in an Apple event attribute that identifies the event class ID for any Apple event in the Core suite. 
  2456. A descriptor record that contains event class data
  2457. Every Apple event includes an attribute that contains the address of the target application. A descriptor record that contains an application’s address is called an address descriptor record.
  2458. TYPE        AEAddressDesc = AEDesc;                                        {address descriptor record}
  2459. As you will see later, the address in an address descriptor record can be specified as an application signature, a process serial number, a session reference number, a target ID record, or a data type that you define.
  2460. Like several of the other data structures defined by the Apple Event Manager for use in Apple event attributes and Apple event parameters, an address descriptor record is identical to a descriptor record of data type AEDesc; the only difference is that an address descriptor record must always contain an application’s address.  
  2461. After the Apple Event Manager has assembled the necessary descriptor records as the attributes and parameters of an Apple event, your application cannot examine the contents of the Apple event directly. Instead, your appolication must use the Apple Event Manager routines to request each attribute and parameter by name. Applications identify attributes and parameters by means of keywords, which are arbitrary names used by the Apple Event Manager to keep track of various descriptor records. The AEKeyword data type is defined as a four-character code.
  2462. TYPE        AEKeyword = PACKED ARRAY[1..4] OF Char;
  2463.                                                 {keyword for a descriptor }
  2464.                                                 { record}
  2465. Constants are typically used for keywords. Here is a list of the keyword constants for Apple event attributes:
  2466. Attribute keyword        Value    Description
  2467. keyAddressAttr         'addr'    Address of target application
  2468. keyEventClassAttr         'evcl'    Event class of Apple event
  2469. keyEventIDAttr        'evid'    Event ID of Apple event
  2470. keyEventSourceAttr        'esrc'    Source of the Apple event
  2471. keyInteractLevelAttr         'inte'    Settings for allowing the Apple Event
  2472.             Manager to bring a server application
  2473.             to the foreground
  2474. keyMissedKeywordAttr        'miss'    First required parameter remaining in
  2475.             an Apple event
  2476. keyOptionalKeywordAttr        'optk'    List of optional parameters
  2477.             for the Apple event
  2478. keyReturnIDAttr         'rtid'    Return ID for reply Apple event 
  2479. keyTimeoutAttr        'timo'    Length of time in ticks that the client
  2480.             will wait for a reply or a result from
  2481.             the server
  2482. keyTransactionIDAttr         'tran'    Transaction ID identifying a series of 
  2483.             Apple events
  2484. Here is a list of the keyword constants for commonly used Apple event parameters:
  2485. Parameter keyword        Value    Description
  2486. keyDirectObject        '----'    Direct parameter
  2487. keyErrorNumber        'errn'    Error number parameter
  2488. keyErrorString        'errs'    Error string parameter
  2489. keyProcessSerialNumber        'psn '    Process serial number parameter 
  2490. The Apple Event Registry: Standard Suites defines additional keyword constants for Apple event parameters that can be used with specific Apple events.
  2491. The Apple Event Manager associates keywords with specific descriptor records by means of a keyword-specified descriptor record, which is a data structure of type AEKeyDesc that consists of a keyword and a descriptor record. 
  2492. TYPE        AEKeyDesc =     {keyword-specified descriptor record}
  2493.         RECORD
  2494.             descKey:                    AEKeyword;                    {keyword}
  2495.             descContent:                    AEDesc;                    {descriptor record}
  2496.         END;
  2497. Figure 2-7 illustrates a keyword-specified descriptor record with the keyword keyEventClassAttr—the keyword that identifies an event class attribute. The figure shows the logical arrangement of the event class attribute for the Open Documents event shown in Figure 2-3 on page 2-14. The descriptor record in Figure 2-7 is identical to the descriptor record shown in Figure 2-6; its descriptor type is typeType, and its data identifies the event class as kCoreEventClass. 
  2498. A keyword-specified descriptor record for the event class attribute of an Open Documents event 
  2499. Descriptor Lists
  2500. When extracting data from an Apple event, you use Apple Event Manager functions to return data in a buffer specified by a pointer, or to return descriptor records containing the data, or to return lists of descriptor records (called descriptor lists) containing the data. As previously noted, the descriptor record (of data type AEDesc) is the fundamental structure in Apple events, and it contains a handle to data. A descriptor list is a data structure of type AEDescList defined by the data type AEDesc—that is, a descriptor list is a descriptor record that contains a list of other descriptor records.
  2501. TYPE        AEDescList = AEDesc;                                    {list of descriptor records}
  2502. Like several other Apple Event Manager data structures, a descriptor list is identical to a descriptor record of data type AEDesc; the only difference is that the data in a descriptor list must always consist of a list of other descriptor records. 
  2503. Figure 2-8 illustrates the logical arrangement of the descriptor list contained by the direct parameter of the Open Documents event shown in Figure 2-3 on page 2-14. This descriptor list consists of a list of descriptor records that contain alias records to filenames. (“The Alias Manager” in Inside Macintosh: Operating System describes alias records in detail.)
  2504. A descriptor list for a list of aliases
  2505. Closely related to a descriptor list is a structure of data type AERecord; in fact, it is defined by the data type AEDescList.
  2506. TYPE        AERecord = AEDescList;                                        {list of keyword-specified }
  2507.                                                 { descriptor records}
  2508. While a descriptor list is a descriptor record that contains a list of other descriptor records, an AE record of data type AERecord is a descriptor record that contains a list of keyword-specified descriptor records describing Apple event parameters. As with other Apple Event Manager data structures based on data type AEDesc, the main difference between a descriptor list and an AE record is the purpose for which each is used. Unlike a descriptor list, an AE record must always contain a list of keyword-specified descriptor records that describe Apple event parameters. It cannot contain keyword-specified descriptor records that describe Apple event attributes.
  2509. An Apple event record is a special descriptor list that consists of a structure of data type AppleEvent, which is defined as an AE record. An Apple event record is used to describe a full-fledged Apple event.
  2510. TYPE        AppleEvent = AERecord;                                        {list of attributes and     }
  2511.                                                 { parameters necessary for }
  2512.                                                 { an Apple event}
  2513. An Apple event record is basically a descriptor record (of descriptor type typeAppleEvent) with a handle to a list of keyword-specified descriptor records. As with other Apple Event data structures based on data type AEDesc, the only difference between an Apple event record and an AE record is the purpose for which each is used. The data handles in an Apple event record’s keyword-specified descriptor records can refer either to attributes or to parameters, whereas the data handles in an AE record’s keyword-specified descriptor records can refer only to parameters. Similarly, an AE record can use only the keywords that identify Apple event parameters, whereas an Apple event record can use keywords that identify either attributes or parameters.
  2514. When you use the AECreateAppleEvent function, the Apple Event Manager creates an Apple event record containing the attributes for an Apple event’s event class, event ID, target address, return ID, and transaction ID. You then use Apple Event Manager functions such as AEPutParamDesc to add parameters to the Apple event. 
  2515. Figure 2-9 shows an example of a complete Apple event—a data structure of type AppleEvent containing a list of keyword-specified descriptor records that name the attributes and parameters of an Open Documents event. The figure includes the event class attribute shown in Figure 2-7 and the descriptor list shown in Figure 2-8, which forms the direct parameter—the keyword-specified descriptor record with the keyword keyDirectObject. The entire figure corresponds to the Open Documents event shown in Figure 2-3 on page 2-14.
  2516. Because the internal structure of an Apple event record is identical to the structure of an AE record, you can pass an Apple event record to any Apple Event Manager function that expects an AE record. Since both are structures of data type AEDescList, which is derived from the data type AEDesc, you can also pass Apple event records and AE records, as well as descriptor lists and descriptor records, to any Apple Event Manager functions that expect records of data type AEDesc.
  2517. The next two sections, “Responding to Apple Events” and “Requesting Services Through Apple Events,” provide a quick overview of the steps your application must take to respond to and send Apple events. 
  2518. Data structures within an Open Documents event
  2519. Responding to Apple Events
  2520. A client application uses the Apple Event Manager to create and send an Apple event requesting a service. A server application responds by using the Apple Event Manager to process the Apple event, to extract data from the attributes and parameters of the Apple event, and to return a result to the client application. The server provides its own routines for performing the action requested by the client’s Apple event. 
  2521. As its first step in supporting Apple events, your application must be able to respond to the required Apple events sent by the Finder. If you plan to implement publish and subscribe capabilities, your application must respond to the Apple events sent by the Edition Manager. Your application should also be able to respond to the standard Apple events that other applications are likely to send to it or that it can send to itself. This section provides a q    uick overview of the tasks your application must perform in responding to Apple events.
  2522. To respond to Apple events, your application must
  2523. n    test for high-level events in its event loop
  2524. n    use the AEProcessAppleEvent function to process Apple events
  2525. n    provide handler routines for the Apple events it supports
  2526. n    use Apple Event Manager functions to extract the parameters and attributes from Apple events
  2527. n    use the AEInteractWithUser function—if your application requires input from the user when your application is responding to an Apple event—to bring your application to the foreground to interact with the user
  2528. n    return a result for the client
  2529. Note that in order for your application to respond to Apple events sent from remote computers, the user of your application must allow network users to link to your application. To do this, the user selects your application in the Finder, chooses Sharing from the File menu, and then clicks the Allow Remote Program Linking check box. If the user has not yet started program linking, the Sharing command offers to display the Sharing Setup control panel so that the user can start program linking. The user must also authorize remote users for program linking by using the Users and Groups control panel. Program linking and setting up authenticated sessions are described in the chapter “Program-to-Program Communications Toolbox” in this book.
  2530. An Apple event (like all high-level events) is identified by a message class of kHighLevelEvent in the what field of the event record. You test the what field of the event record to determine whether an event is a high-level event. If the what field contains the value represented by the kHighLevelEvent constant and your application defines any high-level events other than Apple events, test the message field of the event record to determine whether the high-level event is something other than an Apple event. If the high-level event is not one that you’ve defined for your application, assume that it is an Apple event. (Note that you are encouraged to use Apple events instead of defining your own high-level events whenever possible.)
  2531. After determining that an event is an Apple event, use the AEProcessAppleEvent function to let the Apple Event Manager identify the event. Figure 2-10 shows how the SurfWriter application accepts and begins to process an Apple event sent by the Finder.
  2532. Accepting and processing an Open Documents event
  2533. The AEProcessAppleEvent function first identifies the Apple event by examining the data in the event class and event ID attributes. The AEProcessAppleEvent function then uses that data to call the Apple event handler that your application provides for that event. An Apple event handler is a function that extracts the pertinent data from the Apple event, performs the action requested by the Apple event, and returns a result. For example, if the event has an event class of kCoreEventClass and an event ID of kAEOpenDocuments, the AEProcessAppleEvent function calls your application’s routine for handling the Open Documents event.
  2534. You install Apple event handlers by using the AEInstallEventHandler function. This function creates an Apple event dispatch table that the Apple Event Manager uses to map Apple events to handlers in your application. After being called by the AEProcessAppleEvent function to process an Apple event, the Apple Event Manager reads the Apple event dispatch table and, if your application has installed a handler for that Apple event, calls your handler to finish responding to the event. Figure 2-11 shows how the flow of control passes from your application to the Apple Event Manager and back to your application.
  2535. The Apple Event Manager calling the handler for an Open Documents event
  2536. Your Apple event handlers must generally perform the following tasks:
  2537. n    extract the parameters and attributes for the Apple event
  2538. n    check that all the required parameters have been extracted
  2539. n    locate any Apple event objects specified by object specifier records in the Apple event parameters
  2540. n    set user interaction level preferences if necessary and, if your application needs to interact with the user, use the AEInteractWithUser function to bring it to the foreground
  2541. n    perform the action requested by the Apple event
  2542. n    dispose of any copies of descriptor records that have been created
  2543. n    return a result for the client
  2544. You must use Apple Event Manager functions to extract the data from Apple events. You can also use Apple Event Manager functions to get data out of descriptor records, descriptor lists, and AE records. Most of these routines are available in two forms: one that uses a buffer to return a copy of the desired data, and one that returns a copy of the descriptor record containing the data. The following list shows the main functions you can use to access the data of an Apple event.
  2545. Function        Description
  2546. AEGetParamPtr        Uses a buffer to return the data contained in an Apple event parameter. Used to extract data of fixed length or known maximum length; for example, to extract the result code from the keyErrorNumber parameter of a reply Apple event.
  2547. AEGetParamDesc        Returns the descriptor record or descriptor list for an Apple event parameter. Used to extract data of variable length; for example, to extract the descriptor list for a list of alias records specified in the direct parameter of the Open Documents event.
  2548. AEGetAttributePtr        Uses a buffer to return the data contained in an Apple event attribute. Used to extract data of fixed length or known maximum length; for example, to determine the source of an Apple event by extracting the data from the keyEventSourceAttr attribute.
  2549. AEGetAttributeDesc        Returns the descriptor record for an attribute. Used to extract data of variable length; for example, to make a copy of a descriptor record containing the address of an application.
  2550. AECountItems        Returns the number of descriptor records in a descriptor list. Used, for example, to determine the number of alias records for documents specified in the direct parameter of the Open Documents event.
  2551. AEGetNthPtr        Uses a buffer to return the data for a descriptor record that is contained in a descriptor list. Used to extract data of fixed length or known maximum length; for example, to extract a document’s alias record from the descriptor list specified in the direct parameter of the Open Documents event.
  2552. AEGetNthDesc        Returns a descriptor record from a descriptor list. Used to extract data of variable length; for example, to get the descriptor record containing an alias record from the list specified in the direct parameter of the Open Documents event.
  2553. You can specify the descriptor type of the resulting data for these functions; if this is different from the descriptor type of the attribute or parameter, the Apple Event Manager attempts to coerce it to the specified type. In the direct parameter of the Open Documents event, for example, each descriptor record in the descriptor list is an alias record; each alias record specifies a document to be opened. As explained in the chapter “The File Manager” of Inside Macintosh: Operating System, all your application usually needs is the file system specification (FSSpec) record of the document. When you extract the descriptor from the descriptor list, you can request that the Apple Event Manager return the data to your application as a file system specification record instead of an alias record.
  2554. After extracting all known Apple event parameters, your handler should check that it retrieved all the parameters that the source application considered to be required parameters by determining whether the keyMissedKeywordAttr attribute exists. If the attribute exists, then your handler has not retrieved all the required parameters, and it should return an error.
  2555. The source application is responsible for identifying which Apple event parameters the server should treat as optional. This means that, for a specific event, the source application can force the target application to treat parameters that are listed as optional parameters in the Apple Event Registry: Standard Suites as if they were required, and vice versa. For more information about specifying which parameters the target application should treat as required and which it should treat as optional, see “Specifying Optional Parameters for an Apple Event” on page 2-112.<36pt\>\x12 <8bat\>u
  2556. If any of the Apple event parameters include object specifier records, your handler should use the AEResolve function, other Apple Event Manager routines, and your own application-defined routines to locate the corresponding Apple event objects. For more information about locating Apple event objects on the basis of information in object specifier records, see “Resolving Object Specifier Records” on page 2-53. 
  2557. In some cases, the server may need to interact with the user when it handles an Apple event. For example, your handler for the Print Documents event may need to display a print options dialog box and get settings from the user before printing. Your handler should always use the AEInteractWithUser function before displaying a dialog box or alert box or otherwise interacting with the user. By specifying one of these flags to the AESetInteractionAllowed function, you can set your application’s user interaction level preferences.
  2558. Flag        Description
  2559. kAEInteractWithSelf        User interaction with your server application in response to an Alppe event may be allowed only when your application is also the client application—that is, only when your application is sending the Apple event to itself.
  2560. kAEInteractWithLocal        User interaction with your server application in response to an Apple event may be allowed only if the client application is on the same computer as your application; this is the default if the server application does not call the AESetInteractionAllowed function.
  2561. kAEInteractWithAll         User interaction with your server application inresponse to an Apple event may be allowed for any client application on any computer.
  2562. Both the client and server specify their preferences for user interaction: the client specifies whether the server should be allowed to interact with the user, and the server specifies when it will allow user interaction while processing an Apple event. For the Apple Event Manager to allow a server application to interact with the user in response to a client application’s Apple event, two conditions must be met. First, the client application must set flags in the sendMode parameter of the AESend function that indicate that it allows user interaction. Second, your server application must set the appropriate flag, as described in the preceding list, to allow user interaction in response to the Apple event sent from that client application. If these conditions are met and your application needs to interact with the user, the AEInteractWithUser function brings your application to the foreground if it isn’t already in the foreground. Your application can then display its dialog box or alert box or otherwise interact with the user. AEInteractWithUser brings your server application to the front either directly or after the user responds to a notification request.
  2563. When your application responds to an Apple event, it should perform the standard action requested by that event. For example, if the Apple event is the Open Documents event, your application should open the specified documents in titled windows just as if the user had selected each document from the Finder and then chosen Open from the File menu. 
  2564. You should strive to create routines that can be called in response to both user events and Apple events. To do this, you need to isolate code for interacting with the user from the code that performs the requested action—such as opening a document. You then call the code that performs the requested action from your Apple event handler.<36pt\>\x12 <8bat\>s
  2565. When you extract a descriptor record by using the AEGetParamDesc, AEGetAttributeDesc, AEGetNthDesc, or AEGetKeyDesc function, the Apple Event Manager creates a copy of the descriptor record for you to use. When your handler is finished using a copy of a descriptor record, you should dispose of it—and thereby deallocate the memory it uses—by calling the AEDisposeDesc function.
  2566. Many Apple events can ask your application to return data. For example, if your application is a spelling checker, the client application probably expects data in the form of a list of misspelled words to be returned from your application. Similarly, the Get Data event shown in Figure 2-14 on page 2-44 requests that the server application locate a specific Apple event object and return the data associated with the Apple event object to the client application. 
  2567. If the client application requests a reply, the Apple Event Manager prepares a reply Apple event for the client by passing a default reply Apple event to your handler. If the client application does not request a reply, the Apple Event Manager passes a null descriptor record (a descriptor record of type typeNull, which does not contain any data) to your handler instead of a default reply Apple event. The default reply Apple event has no parameters when it is passed to your handler. Your handler can add any parameters to the reply Apple event. If your application is a spelling checker, for example, you can return a list of misspelled words in a parameter. However, your handler should check the descriptor type of the reply Apple event before attempting to add any attributes or parameters to it. If your handler attempts to add an Apple event attribute or parameter to a null descriptor record, it will generate an error.
  2568. Your handler routine should always set its function result either to noErr if it successfully handles the Apple event or to a nonzero result code if an error occurs. If your handler returns a nonzero result code, the Apple Event Manager adds a keyErrorNumber parameter to the reply Apple event (unless you have already added a keyErrorNumber parameter). This parameter contains the result code that your handler returns. The client should check whether the keyErrorNumber parameter exists to determine whether your handler performed the requested action. In addition to returning a result code, your handler can also return an error string in the keyErrorString parameter of the reply Apple event. The client can use this string in an error message to the user.
  2569. If the client application requested a reply, the Apple Event Manager returns the reply Apple event to the client. The reply Apple event is identified by the event class kCoreEventClass and by the event ID kAEAnswer. When you have finished using the reply Apple event, you should dispose of it—and thereby deallocate the memory it uses—by calling the AEDisposeDesc function.
  2570. When your handler returns a result code to the Apple Event Manager, you have finished your response to the client application’s Apple event. Figure 2-12 shows the entire process of responding to an Apple event. The next section provides a quick overview of the steps your application must take to send Apple events.
  2571. Responding to an Open Documents event  
  2572. Requesting Services Through Apple Events
  2573. Your application can use Apple events to request services from other applications. By using the core Apple event Get Data, for example, your application can request specific data from another application’s documents. By using functional-area Apple events, your application can request services from applications related to your own—for example, asking a spell-checking application to check the text in a document created by your application. Consult the Apple Event Registry: Standard Suites for the format and function of the standard Apple events that your application can send.
  2574. The previous section describes how a server application responds to a client application’s request for services. This section briefly describes the steps your application must take to act as a client application and request such services. To request a service through an Apple event, your application must
  2575. n    create an Apple event by calling the AECreateAppleEvent function
  2576. n    use Apple Event Manager functions to add parameters and any additional attributes to the Apple event
  2577. n    call the AESend function to send the Apple event
  2578. n    dispose of any copies of descriptor records that you have created
  2579. n    process the reply Apple event (if necessary)
  2580. Use the AECreateAppleEvent function to create an Apple event record. Using the arguments you pass to the AECreateAppleEvent function, the Apple Event Manager constructs the data structures describing the event class, the event ID, and the target address attributes of an Apple event. The event class and event ID, of course, identify the particular event you wish to send. The target address identifies the application to which you wish to send the Apple event.
  2581. To act as a server for your application, the target application must support high-level events and must be open. The server can be your own application, another application running on the user’s computer, or an application running on another user’s computer connected to the network. Your application should offer some facility to launch a server application if it is not already running. It is recommended that you use the Open Selection event (identified by the event class kAEFinderEvents and the event ID kAEOpenSelection) to request that the Finder launch applications; however, the Process Manager also provides a means for your application to launch other applications. See the Apple Event Registry: Standard Suites for information on Finder events, and the chapter “Process Management” in Inside Macintosh: Operating System for information on using the Process Manager.
  2582. Your application should also allow the user to choose among the various applications available as servers. The PPCBrowser function allows users to select target applications on their own computers as well as those available on computers connected to the network. The PPCBrowser function presents a standard user interface for choosing a target application, much as the Standard File Package provides a standard user interface for opening and saving files. See the chapter “The Program-to-Program Communications Toolbox” in this book for details on using the PPCBrowser function.
  2583. If the server application is on a remote computer on a network, the user of that computer must allow program linking to the server application. The user of the server application does this by selecting the application in the Finder, choosing Sharing from the File menu, then clicking the Allow Remote Program Linking check box. If the user has not yet started program linking, the Sharing command offers to display the Sharing Setup control panel so that the user can start program linking. The user must also authorize remote users for program linking by using the Users and Groups control panel. Program linking and setting up authenticated sessions are described in the chapter “Program-to-Program Communications Toolbox” in this book.
  2584. You can specify two other attributes in the AECreateAppleEvent function: the reply ID and the transaction ID. For the reply ID attribute, you usually specify the kAutoGenerateReturnID constant to the AECreateAppleEvent function. This constant ensures that the Apple Event Manager generates a unique return ID for the reply Apple event returned from the server. For the transaction ID attribute, you’ll usually specify the kAnyTransactionID constant, which indicates that this Apple event is not one of a series of interdependent Apple events.
  2585. The Apple event record created with the AECreateAppleEvent function serves as a template for the Apple event you want to send. To add the remaining attributes and parameters necessary for your Apple event to the Apple event record, you must use these additional Apple Event Manager functions:
  2586. Function        Description
  2587. AEPutParamPtr        Takes a keyword, descriptor type, and pointer to data and adds the data to an Apple event record as a parameter with the specified keyword (replacing any existing parameter with the same keyword); used, for example, to put numbers into the parameters of an Apple event that asks the server to perform a calculation.
  2588. AEPutParamDesc        Takes a keyword and a descriptor record and adds the descriptor record to an Apple event record as a parameter with the specified keyword (replacing any existing parameter with the same keyword); used, for example, to place a descriptor list containing alias records into the direct parameter of an Apple event that requests a server to manipulate files.
  2589. AEPutAttributePtr        Takes a keyword, descriptor type, and pointer to data and adds the descriptor record to an Apple event record as an attribute with the specified keyword (replacing any existing attribute with the same keyword); used, for example, to change the event ID of an Apple event record that is waiting to be sent.
  2590. AEPutAttributeDesc        Takes a keyword and a descriptor record and adds the descriptor record to an Apple event record as a attribute with the specified keyword (replacing any existing attribute with the same keyword); used, for example, to replace the descriptor record used for the target address attribute in an Apple event record waiting to be sent.
  2591. Descriptor records and descriptor lists are the basic components from which an Apple event record is constructed; these are passed to the AEPutParamDesc and AEPutAttributeDesc functions. Use the following functions to create descriptor records and descriptor lists:
  2592. Function        Description
  2593. AECreateDesc        Takes a descriptor type and a pointer to data and
  2594.         converts them into a descriptor record.
  2595. AEPutPtr        Takes a descriptor type and a pointer to data and adds
  2596.         the data to a descriptor list as a descriptor record; 
  2597.         used, for example, to add to a descriptor list a 
  2598.         number that is used as the parameter of an Apple 
  2599.         event requesting a calculation.
  2600. AEPutDesc        Adds a descriptor record to a descriptor list; used, for
  2601.         example, to add to a descriptor list an alias record 
  2602.         that is used as the direct parameter of an Apple event 
  2603.         requesting file manipulation.
  2604. Apple event parameters for core events and functional-area events can include descriptions of Apple event objects in special records called object specifier records. For an overview of object specifier records and the routines you can use to create them, see “Working With Object Specifier Records,” which begins on page 2-38.
  2605. After you add all the attributes and parameters required for the Apple event, use the AESend function to send the Apple event. The Apple Event Manager uses the Event Manager to transmit the Apple event to the server application.
  2606. The AESend function requires that you specify whether and how your application should wait for a reply from the server. If you specify that you want a reply, the Apple Event Manager prepares a reply Apple event for your application by passing a default reply Apple event to the server. The Apple Event Manager returns any nonzero result code from the server’s handler in the keyErrorNumber parameter of the reply Apple event. The server can return an error string in the keyErrorString parameter of the reply Apple event. The server can also use the reply Apple event to return any data you requested—for example, the results of a numerical calculation or a list of misspelled words.
  2607. You specify how your application should wait for a reply by using one of these flags in the sendMode parameter of the AESend function:
  2608. Flag        Description
  2609. kAENoReply        Your application does not want a reply Apple event.
  2610. kAEQueueReply        Your application wants a reply Apple event; the reply
  2611.         appears in your event queue as soon as the server has
  2612.         the opportunity to process and respond to your Apple
  2613.         event.
  2614. kAEWaitReply        Your application wants a reply Apple event and is
  2615.         willing to give up the processor while waiting for the
  2616.         reply; for example, if the server application is on the
  2617.         same computer as your application, your application
  2618.         yields the processor to allow the server to respond to
  2619.         your Apple event.
  2620. If you specify the kAEWaitReply flag, you may provide an idle function. This function should process any events that occur while your application is waiting for a reply. You supply a pointer to your idle function as a parameter to the AESend function. So that your application can process other Apple events while it is waiting for a reply, you can also specify an optional filter function to the AESend function.
  2621. If you specify the kAENoReply flag, the reply Apple event prepared by the Apple Event Manager for the server application consists of a null descriptor record.
  2622. If your Apple event may require the user to interact with the server application (for example, to specify print or file options), you can communicate your user-interaction preferences to the server by specifying one of the following flags in the sendMode parameter of the AESend function:
  2623. Flag        Description
  2624. kAENeverInteract        The server application should never interact with the 
  2625.         user in response to this Apple event. If this flag is set, 
  2626.         AEInteractWithUser returns the 
  2627.         errAENoUserInteraction result code. This flag is 
  2628.         the default when an Apple event is sent to a remote 
  2629.         application.
  2630. kAECanInteract        The server application can interact with the user in 
  2631.         response to this Apple event—by convention, if the 
  2632.         user needs to supply information to the server. If this 
  2633.         flag is set and the server allows interaction, 
  2634.         AEInteractWithUser either brings the server 
  2635.         application to the foreground or posts a notification 
  2636.         request. This flag is the default when an Apple event is 
  2637.         sent to a local application.
  2638. kAEAlwaysInteract        The server application can interact with the user in 
  2639.         response to this Apple event—by convention, 
  2640.         whenever the server application normally asks a user 
  2641.         to confirm a decision or interact in any other way, 
  2642.         even if no additional information is needed from 
  2643.         the user. If this flag is set     and the server allows 
  2644.         interaction, AEInteractWithUser either brings the 
  2645.         server application to the foreground or posts a 
  2646.         notification request.
  2647. kAECanSwitchLayer        If both the client and server allow interaction, and if 
  2648. the client application is the active application on the local machine and is waiting for a reply (that is, it has set the kAEWaitReply flag), AEInteractWithUser brings the server directly to the foreground. Otherwise, AEInteractWithUser uses the Notification Manager to request that the user bring the server application to the foreground.
  2649. The interpretation of the kAECanInteract and kAEAlwaysInteract flags depends on the server application only, and is not enforced by the Apple Event Manager; the server application must decide whether or not to call AEInterActWIthUser depending on which one is set.
  2650. The server application specifies its own preferences for user interaction while it is processing an Apple event by specifying flags to the AESetInteractionAllowed function, as described in the previous section. The interaction of the client and server applications’ preferences is explained in “Interacting With the User” on page 2-100.
  2651. After you send an Apple event, your application is responsible for disposing of the Apple event record—and thereby deallocating the memory it uses—by calling the AEDisposeDesc function. If you create one descriptor record and add it to another, the Apple Event Manager adds a copy of the newly created one to the existing one. For example, you might use the AECreateDesc function to create a descriptor record that you wish to add to an Apple event. When you use the AEPutParamDesc function, it adds a copy of your newly created descriptor record to an existing Apple event as a parameter.
  2652. Your application should dispose of all the descriptor records that are created in order to add parameters and attributes to an Apple event. You normally dispose of your Apple event and its reply after you receive a result from the AESend function. You should dispose of these even if AESend returns an error result. If your application requests a reply Apple event, your application must also dispose of the reply Apple event when it finishes processing the event.
  2653. Your application can request a reply Apple event. If you specify the kAEWaitReply flag, the reply Apple event is returned in a parameter you pass to the AESend function. If you specify the kAEQueueReply flag to the AESend function, the reply Apple event is returned in the event queue. In this case, the reply is identified by the event class kCoreEventClass and the event ID kAEAnswer; your application processes reply events that it receives in its event queue in the same manner that server applications process Apple events, as described earlier in “Responding to Apple Events.” 
  2654. Your application should check for the keyErrorNumber parameter of the reply Apple event to ensure that the server performed the requested action. Any error messages that the server returns for you to display to your user will appear in the keyErrorString parameter.
  2655. When your handler is finished using a copy of a descriptor record used in the reply Apple event, you should dispose of them both—and thereby deallocate the memory they use—by calling the AEDisposeDesc function.
  2656. The next section provides an overview of the way a source application identifies Apple event objects within a target application or a target application’s documents. If you are starting by supporting only the Required suite and the Apple events sent by the Edition Manager, you can skip the next section and the remainder of this introduction and go directly to “About the Apple Event Manager,” which begins on page 2-57. 
  2657. Working With Object Specifier Records
  2658. Most of the standard Apple events allow the source application to refer, in an Apple event parameter, to Apple event objects within the target application or its documents. The Apple Event Manager allows applications to construct and interpret such references by means of a standard classification system for Apple event objects. This system is fully described by the Apple Event Registry: Standard Suites, and is summarized in “The Classification of Apple Event Objects,” which begins on page 2-45. A description in an Apple event parameter that uses this classification system takes the form of an object specifier record.
  2659. This section describes object specifier records and the data structures used within them. You need to read this section if you plan to support the Core suite or any of the standard functional area suites, and if you want to make your application scriptable—that is, capable of responding to scripts written in a scripting language.
  2660. Object specifier records are descriptor records of descriptor type typeObjectSpecifier that are used by the Apple Event Manager to identify Apple event objects. Object specifier records can specify many combinations of characteristics that cannot be specified using one of the simple data types. For example, you can use object specifier records to specify cells in a table that include certain characters in a specific font, style, color, and point size. However, a client application’s ability to retrieve a specified Apple event object from a server application depends on the server application’s ability to locate the Apple event object. Thus, to locate characters of a specific color, your application must be able to identify a single character’s color; to locate any character in a cell, your application must be able to locate both the table and the cell.
  2661. An Apple event object described by an object specifier record exists only in the server application’s document or in the server application itself, not in the object specifier record. An object specifier record only identifies one or more Apple event objects among many; it contains a description of each Apple event object requested by the client application, not the Apple event object itself. <36pt\>\x12 <8bat\>s
  2662. Object specifier records are only valid while the Apple event that contains them is being handled. For example, if an application receives an Apple event asking it to cut row 5 of a table, what was row 6 then becomes row 5, and the original object specifier record that referred to row 5 no longer refers to the same row.
  2663. A source application can create object specifier records for use as Apple event parameters. Scripting languages can also create object specifier records as Apple event parameters for the Apple events they generate in the course of executing a script. A target application that receives an Apple event containing an object specifier record must resolve the object specifier record—that is, locate the requested Apple event object. 
  2664. To support core and functional-area Apple events received by your application, you must define a hierarchy of Apple event objects within your application and its documents that you want other applications or scripting languages to be able to describe. The hierarchy of Apple event objects for your application should be based as closely as possible on the standard classficiation provided by the Apple Event Registry: Standard Suites. You do not need to write your application in an object-oriented programming language in order to support Apple event objects. Instead, you need to decide which of the standard Apple event objects make sense for your application and write functions that can locate them on the basis of information in an object specifier record. “Resolving Object Specifier Records,” which begins on page 2-53, provides an overview of the way the Apple Event Manager works with your application-defined functions to locate the Apple event objects described in an object specifier record. 
  2665. If you want your application to send specific Apple events to other applications, you must also write functions that can create object specifier records and add them to Apple events. Your application does not need to create object specifier records in order to be scriptable—that is, capable of responding to scripts sent by a scripting language. However, you need to know how object specifier records are constructed in order to write functions that can help the Apple Event Manager resolve them. 
  2666. An object specifier record has four components: 
  2667. n    an object class ID, which specifies the object class of the requested Apple event object 
  2668. n    a description of the container for the requested Apple event object; this usually identifies another Apple event object that contains the requested Apple event object
  2669. n    a key form, which specifies how the Apple Event Manager should interpret the key data
  2670. n    key data, which is used to distinguish the desired Apple event object from other Apple event objects of the same kind in the same container
  2671. For example, an object speciifer record that identifies a table named “Summary of Sales” in a document named “Sales Report” would specify the object class ID that identifies a table; a document named “Sales Report” as the container for the table; a key form constant indicating that the key data contains a name; and key data that consists of the string “Summary of Sales, 1991.”
  2672. The source application usually uses the CreatObjSpecifier function to specify the four components of an object specifier record. The server application uses the AEResolve function and other Apple Event Manager routines to extract information from an object specifier record and uses special routines of its own to locate the specified element on the basis of that information.
  2673. The CreateObjSpecifier routine creates an AE record, which it then coerces to a descriptor record with a descriptor type of typeObjectSpecifier. The typeObjectSpecifier descriptor type denotes an object specifier record: a descriptor record whose contents are defined by four descriptor records of type AEKeyDesc. The internal structure of an object specifier record is nearly identical to an AE record. They differ only in the content referred to by the data handles that they contain. An object specifier record is a structure of data type AEDesc containing four keyword-specified descriptor records that specify one or more Apple event objects; an AE record is a structure of data type AERecord containing one or more Apple event parameters. 
  2674. The four keyword-specified descriptor records that constitute an object specifier record have these keywords:
  2675. Keyword        Value    Description
  2676. keyAEDesiredClass         \qwant\q    Object class ID
  2677. keyAEContainer        \qfrom\q    Identifies the container for this Apple 
  2678.             event object
  2679. keyAEKeyForm        \qform\q    The form taken by the key data
  2680. keyAEKeyData        \qseld\q    The key data
  2681. The object class ID specifies the Apple event object class to which the Apple event object belongs. An object class is a category for Apple event objects that share specific characteristics. The characteristics of each object class are listed in the Apple Event Registry: Standard Suites. For example, the Core suite defines object classes for documents, paragraphs, words, windows, and floating windows. The first keyword-specified descriptor record in an object specifier record, which has the keyword keyAEDesiredClass, specifies yhe object class ID with a four-character code. The object class ID can also be represented by a constant. Constants for object classes always begin with the letter c. The object class for words, for example, can be identified by either the object class ID \qcwor\q or the constant cWord. 
  2682. The object class ID identifies the object class of an Apple event object described in an object specifier record, whereas the event class and event ID identify an Apple event. <36pt\>\x12 <8bat\>u
  2683. The container is usually another Apple event object that contains the Apple event object being specified. For example, the container for a document might be a window, and the container for characters, delimited items, or a word might be another word, a paragraph, or a document. The container is identified by the second keyword-specified descriptor record in an object specifier record, which has the keyword keyAEContainer. Since the container for an Apple event object is usually another Apple event object, this keyword-specified descriptor record usually consists of another object specifier record. It can also consist of a null descriptor record, or it can be used much like a variable when the Apple Event Manager determines a range or performs a series of tests.
  2684. The key form and key data distinguish the desired Apple event object from other Apple event objects of the same object class. The key form describes the form the key data takes. The third and fourth keyword-specified descriptor records in an object specifier record, which have the keywords keyAEKeyForm and keyAEKeyData, specify the key form and key data. Constants for key forms always begin with the word form. A key form of formAbsoluteposition and key data of 5 could be used to specify the fifth Apple event object in the container, such as the fifth row in a table. A key form of formName indicates key data that contains a name. A key form of formProperty indicates key data that specifies a property. 
  2685. Properties are characteristics that can be used to describe Apple event objects belonging to the same class. The properties associated with the object class for documents include the name of the document and a flag that indicates whether the document has been modified since the last save. The properties associated with the object class for words include color, font, point size, and style.
  2686. Other key forms are used to specify relative positions, tests, and ranges. The key data for the key form formRelativePosition might specify that the requested Apple event object is located just after some other Apple event object. The key data for the key form formTest might instruct the server application to locate all the addresses in a database that share the zip code 94133. The key data for a key form of formRange might indicate that the key data specifies a range of Apple event objects.
  2687. The descriptor record that denotes the container for the object specifier record can in turn contain another object specifier record, and so on until the the Apple event object requested by the client application is fully specified. For example, an object specifier record that identifies a paragraph might specify the paragraph’s container with another object specifier record that identifies a page, which in turn might specify its container with another object specifier record that identifies a document. The ability to nest one object specifier record within another object specifier record in this way makes it possible to identify elements such as “the first row in the table named “Summary of Sales, 1991” in the document named “Sales Report.” 
  2688. Figure 2-13 shows the structure of a simple object specifier record, which consists of four keyword-specified descriptor records that specify the class ID, the container, the key form, and the key data. These four keyword-specified descriptor records are the data for a descriptor record (AEDesc) of descriptor type typeObjectSpecifier. Note the similarities between the object specifier record shown in Figure 2-13 and the Apple event record shown in Figure 2-9 on page 2-24. Like an Apple event record or an AE record, an object specifier record consists of a list of keyword-specified descriptor records. 
  2689. Data structures within a simple object specifier record
  2690. An object specifier record whose key form specifies that the key data should be interpreted as a property ID, a name, or an abolute position is called a simple object specifier record, and requires key data that consists of only one keyword-specified descriptor record, as shown in Figure 2-13. An object specifier record whose key form specifies that the key data should be interpreted as a test, a relative position, or a range is called a complex object specifier record, and requires key data that may consist of several interconnected keyword-specified descriptor records.
  2691. Figure 2-14 shows the object specifier record for the Get Data event previously illustrated in Figure 2-4 on page 2-16. The object class ID tells the SurfWriter application that the requested data is an element of class cTable. The container for the table is the document “Sales Report.” The key form is formName, which tells the server application that the key data identifies the Apple event object by name. The key data is the name of the table.
  2692. An object specifier record in a Get Data event
  2693. To add an object specifer record to an Apple event as one of its parameters, your application must first create the object specifier record. “Creating an Object Specifier Record,” which begins on page 2-118, describes the Apple Event Manager routines your application can use to create object specifier records.
  2694. In order to interpret object specifier records correctly, your application must make use of the standard classification system for Apple event objects. The next section summarizes the classification of Apple event objects as defined in the Apple Event Registry: Standard Suites. 
  2695. The Classification of Apple Event Objects
  2696. To create and resolve object specifier records, your application should make use of the classification of Apple event objects defined by the Apple Event Registry: Standard Suites. This section summarizes the concepts that underlie that classification system. You should have a copy of the Apple Event Registry: Standard Suites available for reference purposes while you read this section.
  2697. You need the information in this section only if you plan to implement the core or functional-area Apple events. Before reading this section, you need to understand the concepts described in the preceding section, “Working With Object Specifier Records.”
  2698. You do not need to write your application in an object-oriented programming language in order to support Apple event objects in your application. You do need to understand the classification system described in this section in order to classify Apple event objects within your application and to write routines that can locate them on the basis of information contained in object specifier records.
  2699. Object Classes
  2700. Except for the concept of inheritance, Apple event objects are different from the objects used in object-oriented programming languages. Apple event objects are distinct items in a target application or any of its documents that can be specified by an object specifier record in an Apple event sent by a source application. Apple event objects are often, but not always, items that a user can differentiate and manipulate within an application, such as words, paragraphs, shapes, windows, menu commands, or style formats. Every Apple event object can be classified according to its object class, which defines both its characteristics and its behavior. The object classes listed in the Apple Event Registry: Standard Suites provide a method of describing Apple event objects that can be understood by all applications. Object classes permit more flexibility than simple descriptor types; for example, a word can be defined as a simple string, or it can be defined as an Apple event object with specific characteristics, such as font or style, attached to it.
  2701. The definition of an object class only specifies conventions that determine how applications should handle Apple event objects that belong to that class. Each application must make sure that it uses the conventions correctly; they are not enforced by the Apple Event Manager.<36pt\>\x12 <8bat\>u
  2702. Each object class is identified by a four-character object class ID, which can also be represented by a constant. Constants for object classes always begin with the letter c. For example, the object class for words can be identified by either the object class ID \qcwor\q or the constant cWord. 
  2703. The definition of an object class specifies its superclass, which is the object class from which a subclass (the class being defined) inherits some of its characteristics. Characteristics can also be inherited from special object classes, called abstract superclasses, that are used only in definitions of object classes and do not refer to real Apple event objects. The pattern of inheritance among object classes is called the object class inheritance hierarchy. Figure 2-15 shows a portion of this hierarchy. The abstract superclass cAbstractObject is at the top of the hierarchy, and is therefore the only object class that has no superclass. cText, which is a regular object class, and cOpenableThing, which is an abstract superclass, are both subclasses of cAbstractObject and superclasses for their own subclasses. The object classes cWord, cItem, and cChar are all subclasses of cText, and cWindow, cDocument, and cFile are subclasses of cOpenableThing. Every object class inherits all the characteristics of its superclass, and can also add characteristics of its own.
  2704. Superclasses and subclasses
  2705. Here are some of the object classes defined for the Core suite:
  2706. Class        Class ID    Description
  2707. cChar         'cha '    Text characters
  2708. cClipboard        'clip'    The Clipboard
  2709. cDocument        'docu'    Macintosh documents
  2710. cFile        'cfil'    Macintosh files
  2711. cItem        'citm'    Delimited text strings
  2712. cSelection        'csel'    User or application selections
  2713. cText        'ctxt'    Series of characters
  2714. cWindow        'cwin'    Standard Macintosh windows
  2715. cWord        'cwor'    Words
  2716. Here are some of the object classes defined for the Text Suite:
  2717. Class        Class ID    Description
  2718. cChar         'cha '    Text characters
  2719. cLine        'clin'    Lines of text
  2720. cParagraph        'cpar'    Paragraphs
  2721. cText        'ctxt'    Series of characters
  2722. cTextFlow        'cflo'    Text flows
  2723. cWord        'cwor'    Words
  2724. cWindow        'cwin'    Standard Macintosh windows
  2725. As you can see, some object classes, such as cChar, cText, and cWord, are defined in more than one suite. For example, the definition of the cText object class in the Text suite is an extension of the cText object class defined in the core suite; it duplicates all the characteristics of the Core suite object class and adds some of its own. Like a word in a dictionary, the same object class IDs can have several related definitions. You can choose to support the definition that best suits your application; or, if necessary, you can create extensions of your own. Extensions to object classes are different than inheritance between object classes. An extension of a standard object class provides additional ways of describing an Apple event object of that class, whereas the object class inheritance hierarchy determines the pattern of characteristics shared by different object classes.
  2726. The definition of an object class always specifies a default descriptor type. When a client application requests some data from a server application, such as the data specified by a Get Data, Cut, or Copy event, and the client application does not specify a descriptor type for the returned data, the server application returns a descriptor record of the default descriptor type for the object class of the specified Apple event object. For example, the default descriptor type for Apple event objects of class cWord is typeText, a descriptor type that specifies an undelimited string of characters. The client application can also request that the data be returned in a descriptor record of some other data type. 
  2727. The definition of an object class includes three lists of characteristics: properties, element classes, and Apple events that support the object class. (The next section describes properties and element classes.) Any or all of these characteristics may be inherited from a superclass. An Apple even is listed for an object class if its parameters can specify Apple event objects of that object class. The definition for cWindow, for example, lists fourteen Apple events whose parameters can include object specifier records that specify windows, including the Open, Close, and Move events. The cWindow class inherits all of these Apple events from its abstract superclass, cOpenableThing.
  2728. The Apple Event Registry: Standard Suites also defines primitive object classes, which are used to describe Apple event objects that contain a single value. For example, the cBoolean, cLongInteger, and cAlias object classes are all primitive object classes. The object class ID for a primitive object class is the same as the four-character value of its descriptor type. Primitive object classes contain no properties; they contain only the value of the data.
  2729. Properties and Elements
  2730. The properties listed for an object class are characteristics that can be used to describe Apple event objects that belong to that class. Each property is identified by a four-character property ID, which can also be represented by a constant. Constants for properties always begin with the letter p. Properties are themselves Apple e
  2731. Here are constants and property IDs for some properties:
  2732. Property        Property ID    Description
  2733. pName         'pnam'    Name of an Apple event object
  2734. pBounds        'pbnd'    The coordinates of a window
  2735. pVisible        'pvis'    Indicates whether a window is visible
  2736. pIsModal        'pmod'    Indicates whether a window is modal
  2737. pClass        'pcls'    Class ID of an Apple event object
  2738. pFont        'font'    Font
  2739. pTextStyle        'ptxs'    Text style
  2740. pColor        'colr'    Text color
  2741. pTextPointSize        'ptps'    Point size
  2742. pScriptTag        'psct'    Script system identifier
  2743. pFileInfo        'pfin'    Information about a Macintosh file
  2744. pFillColor        'flcl'    Fill color
  2745. The pName property for a document contains the document’s name. You can use the pName property to describe Apple event objects that have names.
  2746. The pVisible property for a window contains a Boolean value indicating whether or not a window is visible. You can use the pVisible property to check or set the visibility of a window.
  2747. A property is always defined by a single Apple event object. For example, the pFont property of a word is defined by the name of a font, such as New York; the string that identifies the font is an Apple event object of class cFont. 
  2748. Instead of a specific object class, you can specify the constant cProperty as the object class for any object specifier record that identifies a property. An object specifier record for a property specifies the object class ID as cProperty, the Apple event object to which the property belongs as the container, formProperty as the key form, and a constant such as pFont as the key data. For example, if you were sending a Set Data event to change the font of a word to Palatino, the object specifier record for the property would specify cProperty for the class ID, an object specifier record for the word as the container, formProperty as the key form, and pFont as the key data. The Set Data Apple event parameter identified by the keyword keyAETheData would specify Palatino as the text to which to set the value of the specified property. The reply Apple event for a subsequent Get Data event that included an object specifier record for the same property would return the text Palatino in the parameter identified by the keyword keyDirectObject.  
  2749. The elements of a specific Apple event object are the other Apple event objects, excluding those that define its properties, that it contains. An object specifier record for an element specifies the Apple event object in which the element is located as the container, and can specify any key form except for formProperty. Each object class definition in the Apple Event Registry: Standard Suites includes a list of element classes, which are the object classes of the elements that an Apple event object can contain. An Apple event object can contain only one of each of its properties, whereas it can contain many different elements of the same element class. 
  2750. For example, since a paragraph can contain one or more words, one of the element classes listed for the object class cParagraph is the object class cWord. However, a paragraph can have only one pFont property, which is defined as the font of the first character in the paragraph and consists of the name of a font.
  2751. The properties and element classes listed for each object class definition in the Apple Event Registry: Standard Suites can be inherited from a superclass, or they can originate with a subclass. Figure 2-16 illustrates the object class inheritance hierarchy for the object class cWindow in the Core suite. Boldface terms in the figure represent those properties, element classes, or Apple events that are not inherited. The object class cWindow includes all the properties and Apple events of its superclass, cOpenableThing, which in turn includes all the properties and Apple events of its superclass, cAbstractObject. The object class cWindow also includes eight properties and one element class that originate with cWindow and are not inherited. 
  2752. The object class inheritance hierarchy for the object class cWindow
  2753. The pClass property—the property that specifies the four-character class ID—originates with cAbstractObject. Since the definitions of all object classes are ultimately derived from cAbstractObject, pClass is inherited by all object classes. The definition for cAbstractObject also lists 12 Apple events, which include common events such as Get Data, Move, and Delete Element. Because cAbstractObject is at the top of the object class inheritance hierarchy, these twelve Apple events can use object specifier records that describe Apple event objects of any object class as a direct parameter. Like all abstract superclasses, cAbstractObject does not correspond to a real Apple event object, so its definition does not list any element classes. Unlike any other object class, cAbstractObject is at the top of the object class inheritance hierarchy, and therefore does not have a superclass. 
  2754. The chain of containers that determine the location of one or more Apple event objects is called the container hierarchy. The container hierarchy, which specifies the location of real Apple event objects, is different from the object class inheritance hierarchy, which is an abstract concept that determines which properties, element classes, and Apple events an object class inherits from its superclass. For example, the container hierarchy for an Apple event object of class cWord can vary from one word to another, since a word can be contained in various combinations of other Apple event objects, such as a document, a paragraph, a delimited string, or another word. 
  2755. Applications that support Apple event objects must be able to identify the order of several elements of the same class that are contained within another Apple event object. For example, each word in a paragraph should have an identifiable order, such as the fifth word or the twelfth word. This allows other applications to identify Apple event objects by describing their absolute position within a container. 
  2756. Figure 2-17 shows an Apple event object of object class cWord—the word “Sales”—contained in another Apple event object of object class cParagraph. (Both these object classes are defined in the Text suite.) The figure shows only a portion of the container hierarchy for the word, since a complete description of the word would also include the containers that specify the location of the paragraph. 
  2757. Your application must take account of the definitions in the Apple Event Registry: Standard Suites for any object classes you want to support. For example, the definition for the object class cText lists words, characters, and delimited items as Apple event objects that can be contained in Apple event objects of class cText. In order to support Apple events that refer to elements of object class cText, your application can associate the cText object class with words, characters, and delimited items in its documents. The definition for class cText also lists the properties font, style, color, point size, and script tag. If you want to support Apple events that distinguish a boldface 12-point word of object class cText from an italic 14-point word, for example, your application must associate the point size and style of text in its documents with the point size and style properties defined for class cText.
  2758. An Apple event object of class cWord contained in an Apple event object of class cParagraph
  2759.   
  2760. Resolving Object Specifier Records
  2761. If an Apple event parameter consists of an object specifier record, your handler for the Apple event should resolve the object specifier record: that is, locate the Apple event objects it describes. The first step is to call the AEResolve function with the object specifier record as a parameter. The AEResolve function performs tasks that are required to resolve any object specifier record, such as parsing its contents, keeping track of the results of tests, and handling memory management. When necessary, AEResolve calls application-defined functions to perform tasks that are unique to the application, such as locating a specific Apple event object in the application’s data structures or counting the number of Apple event objects in a container.
  2762. The section “Responding to Apple Events,” which begins on page 2-25, provides an overview of the steps your application must take in order to respond to Apple events. This section describes how you can use the Apple Event Manager and your own application-defined routines to resolve any object specifier records contained within Apple events to which you want your application to respond.
  2763. The AEResolve function can call two kinds of application-defined functions. Object accessor functions locate Apple event objects. Every application that supports simple object specifier records must provide one or more object accessor functions. This section provides an overview of the way AEResolve calls object accessor functions when it resolves object specified records. Object callback functions perform other tasks that only an application can perform, such as counting, comparing, or marking Apple event objects. You can provide up to seven object callback functions, depending on the needs of your application. 
  2764. Each time AEResolve calls one of your application’s object accessor functions successfully, the object accessor function returns a special descriptor record created by your application, called a token, that identifies either a requested Apple event object in a specified container or a requested property of a specified Apple event object. AEResolve examines the token’s descriptor type, but does nothing with the token’s data; it simply passes the token back to your application when it needs to refer to the Apple event object or property the token identifies. 
  2765. Each object accessor function provided by your application should either find elements of a specified object class contained in an Apple event object identified by a token of a specified descriptor type, or find properties of an Apple event object identified by a token of a specified descriptor type. The Apple Event Manager uses the object class ID of the specified Apple event object or property and the descriptor type of the token that identifies its container to determine which object accessor function to call.
  2766. It is up to you to decide how many object accessor functions you need to write for your application. You can write one object accessor function that locates Apple event objects of several different object classes; or you can write separate object accessor functions for certain object classes. Similarly, you may want to use only one descriptor type for all the tokens returned by your object accessor functions, or you may want to use several descriptor types. The way you define your tokens depends on the the needs of your application. 
  2767. You install object accessor functions by using the AEInstallObjectAccessor function. Much like the AEInstallEventHandler function, AEInstallObjectAccessor creates an object accessor dispatch table that the Apple Event Manager uses to map requests for Apple event objects or properties of a specified object class in containers identified by a token of a specified descriptor type to the appropriate object accessor function in your application. Depending on the container hierarchy for a given object specifier record and the way your application defines its object accessor functions, the Apple Event Manager may need to call a series of object accessor functions in order to resolve the object specifier records nested in the keyword-specified descriptor record that describes an Apple event object’s container.
  2768. Figure 2-18 illustrates the major steps involved in resolving an object specifier record. The SurfWriter application shown in Figure 2-18 receives a Get Data event whose direct parameter is an object specifier record for a table named “Summary of Sales, 1991” in a document named “Sales Report.” The SurfWriter application’s handler for the Get Data event calls the AEResolve function with the object specifier record as a parameter. The AEResolve function begins to parse the object specifier record. The first object accessor function that AEResolve calls is always the function that can identify the Apple event object in the default container. (An application’s default container is the outermost container in the container hierarchy.) In Figure 2-18, the object specifier record for the document “Sales Report” specifies the default container, so the Apple Event Manager calls the object accessor function in the SurfWriter application that can locate a document in a containers identified by a token of descriptor type typeNull. 
  2769. After the SurfWriter application has located the document named “Sales Report,” it returns a token to the Apple Event Manager—that is, a descriptor record that the SurfWriter application uses to identify the document. The Apple Event Manager examines the descriptor type of the token, but does not need to know anything about the token’s data in order to continue parsing the object specifier record. The next object accessor function it calls will be the function that can identify a table in a container identified by a token of descriptor type typeMyDocToken; when the Apple Event Manager calls this object accessor function, it passes the token describing the document to the function in order to specify the container for the requested table. After the SurfWriter application has located thetable named “Summary of Sales” in the document named “Sales Report,” it returns a token describing that table to the Apple Event Manager. 
  2770. Resolving an object specifier record for a table in a document
  2771. Since the token returned to the Apple Event Manager at each stage provides all the information your application needs to locate the corresponding Apple event object, the Apple Event Manager needs to keep track of only one token at a time. Therefore, when your application returns a token to the Apple Event Manager, the previous token, if any, is no longer needed. The Apple Event Manager disposes of a token by calling either the AEDisposeDesc function or your application’s token disposal function, if you have provided one, which is an object callback function that disposes of a token. In Figure 2-18, the AEResolve function calls the SurfWriter application’s token disposal function after it recieves the token for the table in order to dispose of the token for the document. After the SurfWriter application has disposed of the token for the document, the AEResolve function returns the result of the resolution—that is, the token for the requested table—to the handler in the SurfWriter application that originally called AEResolve.
  2772. The Apple Event Manager can complete the cycle of parsing the object specifier record, calling the appropriate object accessor function to obtain a token, and disposing of the previous token as many times as it needs to in order to identify every container in the container hierarchy and finish resolving an object specifier record. However, one token will always be left over—the token that identifies the Apple event object requested by the Apple event (the innermost element in the container hierarchy). After your application receives this final token as the result of the AEResolve function and performs the action requested by the Apple event, it is up to your application to dispose of the token. Your application can do so by calling the AEDisposeToken function, which in turn calls either AEDisposeDesc or your application’s token disposal function. 
  2773. You need to provide a token disposal function only if your application needs to do more than call AEDisposeDesc to dispose of a token, or if you provide marking callback functions, which are three object callback functions that allow your application to use its own marking scheme rather than tokens when identifying large groups of Apple event objects. Your application is not required to provide marking callback functions. 
  2774. Applications that support complex object specifier records must provide at least two object callback functions: an object counting callback function, which counts the number of elements of a given object class in a given container so that the Apple Event Manager can determine how many elements it must test to find the element or elements that meet a specified condition; and an object comparison callback function, which compares one element to another element or to a descriptor record and returns TRUE or FALSE. 
  2775. Your application may also provide an error callback function that can identify which descriptor record caused the resolution of an object specifier record to fail. Your application is not required to provide an error callback function.
  2776. If your application resolves object specifier records without the help of the Apple Event Manager, it must coerce the object specifier records into the equivalent descriptor records and then extract the necessary information from the descriptor records. The Apple Event Manager includes coercion handlers for these coercions.
  2777. For information about object accessor functions, see “Writing Object Accessor Functions,” beginning on page 2-157. For information about object callback functions, see “Writing Object Callback Functions,” beginning on page 2-173.  
  2778. About the Apple Event Manager 
  2779. You can use the Apple Event Manager to 
  2780. n    respond to the Apple events in the Required suite (Open Application, Open Documents, Print Documents, and Quit Application) that are sent by the Finder
  2781. n    respond to the Apple events sent by the Edition Manager and allow users to share data among documents created by multiple applications
  2782. n    respond to Apple events sent by other applications in order to request a service or information from your application
  2783. n    send Apple events to other applications in order to request services or information from them
  2784. n    respond to Apple events sent to your application by a script written in a scripting language such as AppleScript
  2785. The section “Introduction to Apple Events,” which begins on page 2-6, explains important concepts you need to know before you begin to implement Apple events in your own application. You do not need to implement all Apple events at once. If you want to begin by supporting only the required Apple events, you must
  2786. n    set bits in the 'SIZE' resource to indicate that your application supports high-level events
  2787. n    include code to handle high-level events in your main event loop
  2788. n    install entries for the required Apple events in your application’s Apple event dispatch table 
  2789. n    write routines that handle the Required events
  2790. The following sections explain how to perform these tasks: “Accepting an Apple Event,” which begins on page 2-60, “Installing Entries in the Apple Event Dispatch Tables,” which begins on page 2-63, and “Handling the Required Apple Events,” which begins on page 2-72.
  2791. To support the Apple events sent by the Edition Manager in addition to the Required events, you must install entries for the Section Read, Section Write, Section Scroll, and Create Publisher events in your application’s Apple event dispatch table and write the corresponding handlers, as described in “Handling Apple Events Sent by the Edition Manager,” which begins on page 2-81. 
  2792. It is relatively easy to support the required events and the events sent by the Edition Manager; however, if your application does not support any other Apple events, other applications will not be able to request services that involve locating specific Apple event objects within your application or its documents, and your application will not be able to respond to scripts. To provide full support for Apple events, your application must support both the Core suite of Apple events and any of the other functional-area standard suites that make sense for your application. For example, most word-processing applications would need to support the Text Suite, and most graphics applications would need to support the QuickDraw Graphics suite in addition to the Required suite and the Core suite. 
  2793. By supporting all the suites in the Apple Event Registry: Standard Suites that are appropriate for your application, you ensure that your application can communicate effectively with all the other applications that support them. Instead of supporting many different custom events for a limited number of applications, you can support a small number of standard Apple events that can be used by any number of applications. Supporting the standard Apple events also ensures that you can make your application scriptable, or capable of responding to instructions written in a system-wide scripting language such as AppleScript.
  2794. To support any of the suites defined in the Apple Event Registry: Standard Suites besides the Required suite, you must also support the Apple event objects that can be described within Apple events that belong to the suites. Once you have provided the basic level of support for the Required suite and for events sent by the Edition Manager, you should
  2795. n    decide which other Apple event suites you want to support
  2796. n    define the hierarchy of Apple event objects within your application that you want other processes to be able to identify—that is, which Apple event objects can be contained by other Apple event objects in your application
  2797. n    write routines that can handle the Apple events you support, and install corresponding entries in your application’s Apple event dispatch table 
  2798. n    write routines that can create the Apple events, including object specifier records if necessary, that you want your application to send to other applications 
  2799. n    write object accessor functions that can locate the Apple event objects you support, and install corresponding entries in your application’s object accessor dispatch table
  2800. n    write any object callback functions that you decide to provide for optimizing the way your application locates requested Apple event objects
  2801. To decide which Apple event suites you want to support and how to define the hierarchy of Apple event objects in your application, consult the Apple Event Registry: Standard Suites and evaluate which Apple events and Apple event object classes make sense for your application. If necessary, you can extend the definitions of the standard Apple events and Apple events objects to cover special requirements of your application; it is preferable to extend the standard definitions rather than defining your own custom Apple events, since only those applications that choose to support your custom Apple events explicitly will be able to make use of them. 
  2802. The next section, “Using the Apple Event Manager,” provides detailed information on writing and installing Apple event handlers and related functions, creating and sending Apple events, and writing and installing object accessor and object callback functions. 
  2803. 2The Apple Event Manager
  2804. Using the Apple Event Manager
  2805. The following sections explain in detail how to use the Apple Event Manager to accept, respond to, and send Apple events. The first three sections describe how to accept and process Apple events and how to install entries in the Apple event and object accessor dispatch tables. The fourth section fully explains how your application should handle the required Apple events, and it provides code that shows sample handlers for the required Apple events.
  2806. Additional sections describe how to
  2807. n    handle events that support publish and subscribe features
  2808. n    get data out of an Apple event
  2809. n    write handlers that perform the action requested by an Apple event
  2810. n    reply to an Apple event
  2811. n    dispose of Apple event data structures
  2812. n    interact with the user when processing an Apple event
  2813. n    create an Apple event
  2814. n    create an object specifier record
  2815. n    send an Apple event
  2816. n    write an idle function
  2817. n    write a reply filter function
  2818. n    write and install coercion handlers
  2819. n    write object accessor functions 
  2820. n    write object callback functions
  2821. The Apple Event Manager (excluding the routines that support Apple event objects) is available only in system software version 7.0 and later versions. Use the Gestalt function with the gestaltAppleEventsAttr selector to determine whether the Apple Event Manager is available. In the response parameter, the bit defined by the constant gestaltAppleEventsPresent is set if the Apple Event Manager is available.
  2822. CONST        gestaltAppleEventsAttr    = 'evnt';                                                {Gestalt selector}
  2823.         gestaltAppleEventsPresent = 0;                                                {if this bit is set, } 
  2824.                                                         { then the Apple Event}
  2825.                                                         { Manager is available}
  2826. To support the Apple events in the Core Suite and the functional area suites described in the Apple Event Registry: Standard Suites, your application must support Apple event objects. To make use of the Apple Event Manager routines that allow your application support Apple event objects, you must link the Object Support Library with your application when you build it, and call the AEObjectInit function before calling any of those routines.
  2827. Accepting an Apple Event
  2828. To accept or send Apple events (or any other high-level events), you must set the appropriate flags in your application’s 'SIZE' resource and include code to handle high-level events in your application’s main event loop. 
  2829. Two flags in the 'SIZE' resource determine whether an application receives high-level events: 
  2830. n    The isHighLevelEventAware flag must be set for your application to receive any high-level events.
  2831. n    The localAndRemoteHLEvents flag must be set for your application to receive high-level events sent from another computer on the network.
  2832. Note that in order for your application to respond to Apple events sent from remote computers, the user of your application must also allow network users to link to your application. The user does this by selecting your application in the Finder, choosing Sharing from the File menu, and clicking the Allow Remote Program Linking checkbox. If the user has not yet started program linking, the Sharing command offers to display the Sharing Setup control panel so that the user can start program linking. The user must also authorize remote users for program linking by using the Users and Groups control panel. Program linking and setting up authenticated sessions are described in the Program-to-Program Communications Toolbox chapter in this volume.
  2833. For a complete description of the 'SIZE' resource, see the chapter “The Event Manager” in Inside Macintosh: Macintosh Toolbox.
  2834. Apple events (and other high-level events) are identified by a message class of kHighLevelEvent in the what field of the event record. You can test the what field of the event record to determine whether the event is a high-level event.
  2835. Listing 2-1 is an example of a procedure called from an application’s main event loop that handles events, including high-level events. The procedure determines the type of event received and then calls another routine to take the appropriate action.
  2836. A DoEvent procedure
  2837. PROCEDURE DoEvent (event: EventRecord);
  2838.  
  2839. BEGIN                
  2840.     CASE event.what OF                                    {determine the type of event}
  2841.         mouseDown:
  2842.             DoMouseDown (event);
  2843.         .
  2844.         . {handle other kinds of events}
  2845.         .
  2846.         {handle high-level events, including Apple events}
  2847.         kHighLevelEvent:
  2848.             DoHighLevelEvent (event);
  2849.     END;
  2850. END; 
  2851. Listing 2-2 is an example of a DoHighLevelEvent procedure that handles Apple events and also handles the high-level event identified by the event class mySpecialHLEventClass and the event ID mySpecialHLEventID. Note that, in most cases, you should use Apple events to communicate with other applications. 
  2852. Listing 2-2    A DoHighLevelEvent procedure for handling Apple events and other high-level events
  2853. PROCEDURE DoHighLevelEvent (event: EventRecord);
  2854.  
  2855. VAR
  2856.     myErr: OSErr;
  2857. BEGIN
  2858.     IF (event.message = LongInt(mySpecialHLEventClass)) AND
  2859.         (LongInt(event.where) = LongInt(mySpecialHLEventID)) THEN
  2860.     BEGIN
  2861.     {it's a high-level event that doesn't use AEIMP}
  2862.         myErr := HandleMySpecialHLEvent(event);
  2863.         IF myErr <> noErr THEN
  2864.             DoError(myErr);    {perform the necessary error handling}
  2865.     END
  2866.     ELSE        {otherwise, assume that the event is an Apple event}
  2867.     BEGIN
  2868.         myErr := AEProcessAppleEvent(event);
  2869.         IF myErr <> noErr THEN
  2870.             DoError(myErr);
  2871.     END;
  2872. END;
  2873. If your application accepts high-level events that do not follow the Apple Event Interprocess Messaging Protocol (AEIMP), you must dispatch these high-level events before calling AEProcessAppleEvent. To dispatch a high-level event that does not follow AEIMP, for each event you should check the event class, the event ID, or both to see if the event is one that your application can handle. 
  2874. After receiving a high-level event (and, if appropriate, checking to see whether it is a type of high-level event other than an Apple event), your application typically calls the AEProcessAppleEvent function. The AEProcessAppleEvent function determines the type of Apple event received, gets the event buffer that contains the parameters and attributes of the Apple event, and calls the corresponding Apple event handler routine in your application.
  2875. You should provide a handler routine for each Apple event that your application supports. Your handler routine for a particular Apple event is responsible for performing the action requested by the Apple event, and your handler can optionally return data in the reply Apple event. 
  2876. If the client application requests a reply, the Apple Event Manager passes a default reply Apple event to your handler. If the client application does not request a reply, the Apple Event Manager passes a null descriptor record (a descriptor record of type typeNull, which does not contain any data) to your handler instead of a default reply Apple event. 
  2877. After your handler finishes processing the Apple event and adds any parameters to the reply Apple event, it should return a result code to AEProcessAppleEvent. If the client application is waiting for a reply, the Apple Event Manager returns the reply Apple event to the client.
  2878. Installing Entries in the Apple Event Dispatch Tables
  2879. When your application receives an Apple event, use the AEProcessAppleEvent function to retrieve the data buffer of the event and to route the Apple event to the appropriate Apple event handler in your application. Your application supplies an Apple event dispatch table to map the Apple events your application supports to the Apple event handlers provided by your application.
  2880. To create your application’s Apple event dispatch table (if it does not already exist) or install additional entries in it, use the AEInstallEventHandler function. You usually install entries for all of the Apple events that your application accepts into your application’s Apple event dispatch table. 
  2881. For each Apple event your application supports, your Apple event dispatch table should include entries that specify
  2882. n    the event class of the Apple event
  2883. n    the event ID of the Apple event
  2884. n    the address of the Apple event handler for the Apple event
  2885. n    a reference constant
  2886. You provide this information to the AEInstallEventHandler function. In addition, you indicate to the AEInstallEventHandler function whether the entry should be added to your application’s Apple event dispatch table or the system Apple event dispatch table. 
  2887. The system Apple event dispatch table is a table in the system heap that contains system Apple event handlers—handlers that are available to all applications and processes running on the same computer. The handlers in your application’s Apple event dispatch table are available only to your application. If AEProcessAppleEvent cannot find a handler for the Apple event in your application’s Apple event dispatch table, it looks in the system Apple event dispatch table for a handler. If it doesn’t find a handler there either, it returns the errAEEventNotHandled result code.
  2888. Listing 2-3 illustrates how to add entries for the required Apple events to your application’s Apple event dispatch table.
  2889. Listing 2-3    Adding entries for the required Apple events to an application’s Apple event dispatch table
  2890. myErr := AEInstallEventHandler(kCoreEventClass, 
  2891.                                             kAEOpenApplication, 
  2892.                                             @MyHandleOAPP, 0, FALSE);
  2893. IF myErr <> noErr THEN DoError(myErr);
  2894. myErr := AEInstallEventHandler (kCoreEventClass, kAEOpenDocuments, 
  2895.                                            @MyHandleODOC, 0, FALSE);
  2896. IF myErr <> noErr THEN DoError(myErr);
  2897. myErr := AEInstallEventHandler (kCoreEventClass, 
  2898.                                             kAEPrintDocuments, 
  2899.                                             @MyHandlePDOC, 0, FALSE);
  2900. IF myErr <> noErr THEN DoError(myErr);
  2901. myErr := AEInstallEventHandler (kCoreEventClass,
  2902.                                         kAEQuitApplication, @MyHandleQUIT, 
  2903.                                         0, FALSE); 
  2904. IF myErr <> noErr THEN DoError(myErr);    
  2905. The code in Listing 2-3 creates entries for all four required Apple events in the Apple event dispatch table. (For examples of handlers that correspond to these entries, see “Handling the Required Apple Events,” which begins on page 2-72.) The first entry creates an entry for the Open Application event. The entry indicates the event class and event ID of the Open Application event, supplies the address of the handler for that event, and specifies 0 as the reference constant. 
  2906. The reference constant is passed to your handler by the Apple Event Manager each time your handler is called. Your application can use this reference constant for any purpose. If your application doesn’t use the reference constant, use 0 as the value. 
  2907. The last parameter to the AEInstallEventHandler function is a Boolean value that determines whether the entry is added to the system Apple event dispatch table or to your application’s Apple event dispatch table. To add the entry to your application’s Apple event dispatch table, use FALSE as the value of this parameter. If you specify TRUE, the entry is added to the system’s Apple event dispatch table. The code shown in Listing 2-3 adds entries to the application’s Apple event dispatch table.
  2908. If your application supports the Edition Manager, you should also add entries to your application’s Apple event dispatch table for the Apple events that your application receives from the Edition Manager. Listing 2-4 shows how to add these entries.
  2909. Listing 2-4    Adding entries for Apple events sent by the Edition Manager to an application’s Apple event dispatch table
  2910. myErr := AEInstallEventHandler(sectionEventMsgClass, 
  2911.                                          sectionReadMsgID, 
  2912.                                          @MyHandleSectionReadEvent, 
  2913.                                          0, FALSE);
  2914. IF myErr <> noErr THEN DoError(myErr);
  2915. myErr := AEInstallEventHandler(sectionEventMsgClass, 
  2916.                                          sectionWriteMsgID, 
  2917.                                          @MyHandleSectionWriteEvent, 
  2918.                                          0, FALSE);
  2919. IF myErr <> noErr THEN DoError(myErr);
  2920. myErr := AEInstallEventHandler(sectionEventMsgClass, 
  2921.                                              sectionScrollMsgID, 
  2922.                                          @MyHandleSectionScrollEvent, 
  2923.                                          0, FALSE);
  2924. IF myErr <> noErr THEN DoError(myErr);
  2925. See “Handling Apple Events Sent by the Edition Manager” on page 2-81 for the parameters associated with these events. See the chapter “The Edition Manager” in this book for information on how your application should respond to the Apple events sent by the Edition Manager.
  2926. If you add a handler to the system Apple event dispatch table, the handler that you specify must reside in the system heap. If there was already an entry in the system Apple event dispatch table for the same event class and event ID, it is replaced unless you should chain it to your system handler as explained in “Creating and Managing the Apple Event Dispatch Tables” on page 2-183. 
  2927. When an application calls a system Apple event handler, the A5 register is set up for the calling application. For this reason, if you provide a system Apple event handler, it should never use A5 global variables or anything that depends on a particular context; otherwise, the application that calls the system handler may crash.<36pt\>\x12 <8bat\>u
  2928. When the AEProcessAppleEvent function begins to process an Apple event, it first searches the application’s Apple event dispatch table, then the system Apple event dispatch table for the entry that corresponds to the Apple event’s event class and event ID. If the AEProcessAppleEvent function cannot find an entry for an Apple event’s handler in either table, it returns the result code errAEEventNotHandled to the Apple event server. If the client is waiting for a reply, AESend also returns this result code as its function result.
  2929. For any entry in your Apple event dispatch table, you can specify a wildcard value for the event class, event ID, or both. You specify a wildcard by supplying the typeWildCard constant when installing an entry into the Apple event dispatch table. A wildcard value matches all possible values. Wildcards make it possible to supply one Apple event handler that dispatches several related Apple events.
  2930. For example, if you specify an entry with the typeWildCard event class and the kAEOpenDocuments event ID, the Apple Event Manager dispatches Apple events of any event class with an event ID of kAEOpenDocuments to the handler for that entry. 
  2931. If you specify an entry with the kCoreEventClass event class and the typeWildCard event ID, the Apple Event Manager dispatches Apple events of the kCoreEventClass event class with any event ID to the handler for that entry. 
  2932. If you specify an entry with the typeWildCard event class and the typeWildCard event ID, the Apple Event Manager dispatches all Apple events of any event class and any event ID to the handler for that entry.
  2933. If an Apple dispatch table contains one entry for an event class and a specific event ID, and also contains another entry that is identical except that it specifies a wildcard value for either the event class or the event ID, the Apple Event Manager will dispatch the more specific entry. For example, if an Apple event dispatch table includes one entry that specifies the event class as kAECoreSuite and the event ID as kAEDelete, and another entry that specifies the event class as kAECoreSuite and the event ID as typeWildCard, the Apple Event Manager will dispatch the Apple event handler associated with the entry that specifies the event ID as kAEDelete.
  2934. If your application sends Apple events to itself using a typeProcessSerialNumber address descriptor record with the value kCurrentProcess, the Apple Event Manager jumps directly to the appropriate Apple event handler without going through the normal event-processing sequence. As a result, your application will not run appreciably more slowly when it sends Apple events to itself. Because the Apple Event Manager calls your application’s Apple event handlers directly, without going through the PPC Toolbox, Apple events your application sends to itself do not appear in your application’s high-level event queue.<36pt\>\x12 <8bat\>s
  2935. Installing Entries in the Object Accessor Dispatch Tables
  2936. Most of the Apple events in the Core suite and the functional-area suites defined in the Apple Event Registry: Standard Suites can include parameters that consist of object specifier records. If the direct parameter for an Apple event consists of an object specifier record, your handler for the event should call the AEResolve function to resolve the object specifier record: that is, to find the Apple event objects it describes and, if necessary, their properties. AEResolve resolves the object specifier record with the help of object accessor functions provided by your application. Your application supplies an object accessor dispatch table that the Apple Event Manager uses to map requests for Apple event objects or their properties to the appropriate object accessor functions. (For an overview of the way AEResolve works with your application’s object accessor functions to locate Apple event objects, see “Resolving Object Specifier Records,” which begins on page 2-53.)
  2937. Each time AEResolve calls one of your application’s object accessor functions, your object accessor function should return a token that identifies the specified Apple event object or a specified property of an Apple event object. Your object accessor function also returns a result code that indicates whether or not it found the Apple event object or property. The token, which is a descriptor record of data type AEDesc, can be of any descriptor type, including descriptor types you define yourself. 
  2938. Each object accessor function provided by your application should either find elements of a specified object class contained in an Apple event object identified by a token of a specified descriptor type, or find properties of an Apple event object identified by a token of a specified descriptor type. The Apple Event Manager uses the object class ID of the specified Apple event object and the descriptor type of the token that identifies its container to determine which object accessor function to dispatch. For object accessor functions that find properties, you should specify the object class ID as the constant cProperty. 
  2939. To create your application’s object accessor dispatch table (if it does not already exist) or install additional entries in it, use the AEInstallObjectAccessor function. For each object class and property your application supports, you should install entries that specify
  2940. n    the object class of the requested Apple event object or property
  2941. n    the descriptor type of the token used to identify the container for the requested Apple event object or property
  2942. n    the address of the object accessor function that finds Apple event objects or properties of the specified object class in containers described by tokens of the specified descriptor type
  2943. n    a reference constant
  2944. You provide this information in the first four parameters to the AEInstallObjectAccessor function. The fifth parameter allows you to indicate whether the entry should be added to your application’s object accessor dispatch table or the system object accessor dispatch table.
  2945. The system object accessor dispatch table is a table in the system heap that contains object accessor functions that are available to all processes running on the same computer. The object accessor functions in your application’s object accessor dispatch table are available only to your application. If AEResolve cannot find an object accessor function for the Apple event object class in your application’s object accessor dispatch table, it looks in the system object accessor dispatch table for an object accessor function. If it doesn’t find an object accessor function there either, it returns the result code errAEEventNotHandled.
  2946. If the AEResolve function successfully calls the appropriate object accessor function in either the application object accessor dispatch table or the system object accessor dispatch table, the object accessor function returns a token and result code, which AEResolve uses either to continue resolving the object specifier record or, if the token identifies the final Apple event object or property in the container hierarchy, to return as its function result. 
  2947. It is up to you to decide how many object accessor functions you need to write and install for your application. You can install one object accessor function that locates Apple event objects of several different object classes, or you can write separate object accessor functions for certain object classes. Similarly, you may want to use only one descriptor type for all the tokens returned by your object accessor functions, or you may want to use several descriptor types. The sections that follow provide examples of alternative approaches.
  2948. For more information about object accessor functions, see “Writing Object Accessor Functions,” which begins on page 2-157.
  2949. Installing Object Accessor Functions That Find Apple Event Objects
  2950. Listing 2-5 demonstrates how to add entries to your application’s object accessor dispatch table for the object class cText and three of its element classes: the object classes cWord, cItem, and cChar. In this example, the container for each of these object classes is identified by a token that consists of a descriptor record of descriptor type typeMyText. 
  2951. Listing 2-5    Adding entries to an application’s object accessor dispatch table for object accessor functions that locate elements of different object classes in containers identified by tokens of the same descriptor type
  2952. myErr := AEInstallObjectAccessor(cText, typeMyText, 
  2953.                                             @MyFindTextObjectAccessor,
  2954.                                             0, FALSE);
  2955. IF myErr <> noErr THEN DoError(myErr);
  2956. myErr := AEInstallObjectAccessor(cWord, typeMyText, 
  2957.                                             @MyFindWordObjectAccessor,
  2958.                                             0, FALSE);
  2959. IF myErr <> noErr THEN DoError(myErr);
  2960. myErr := AEInstallObjectAccessor(cItem, typeMyText, 
  2961.                                             @MyFindItemObjectAccessor,
  2962.                                             0, FALSE);
  2963. IF myErr <> noErr THEN DoError(myErr);
  2964. myErr := AEInstallObjectAccessor(cChar, typeMyText, 
  2965.                                             @MyFindCharObjectAccessor,
  2966.                                             0, FALSE);
  2967. IF myErr <> noErr THEN DoError(myErr);    
  2968. The first call to AEInstallObjectAccessor in Listing 2-5 adds an entry to the application’s object accessor dispatch table indicating that the AEResolve function should call the MyFindTextObjectAccessor function when resolving any Apple event object with the cText object class and a container identified by a token of descriptor type typeMyText. The other calls to AEInstallObjectAccessor in Listing 2-5 add entries for Apple event objects of object classes cWord, cItem, and cChar in a container identified by a token of descriptor type typeMyText. For example, since all the entries created by the code in Listing 2-5 specify the descriptor type typeMyText for the token that identifies the container, the AEResolve function will call the MyFindWordObjectAccessor function to locate a requested word regardless of whether the container for the word is a run of text, another word, a paragraph, or an item. 
  2969. The fourth parameter for the AEInstallObjectAccessor function specifies a reference constant that is passed to your handler by the Apple Event Manager each time AEResolve calls your object accessor function. Your application can use this reference constant for any purpose. If your application doesn’t use the reference constant, use 0 as the value, as shown in Listing 2-5.
  2970. The last parameter for the AEInstallObjectAccessor function is a Boolean value that determines whether the entry is added to the system object accessor dispatch table or to your application’s object accessor dispatch table. To add the entry to your application’s object accessor dispatch table, use FALSE as the value of this parameter. If you specify TRUE, the entry is added to the system’s object accessor dispatch table.
  2971. If you add an object accessor function to the system object accerssordispatch table, the function that you specify must reside in the system heap. If there was already an entry in the system object accessor dispatch table for the same object class and container descriptor type, it is replaced. 
  2972. When an application calls a system object accessor function, the A5 register is set up for the calling application. For this reason, if you provide a system object accessor function, it should never use A5 global variables or anything that depends on a particular context; otherwise, the application that calls the system object accessor function may crash.<36pt\>\x12 <8bat\>u
  2973. The code shown in Listing 2-5 installs a separate object accessor function for each object class, even though it specifies the same descriptor type for tokens that identify the containers for Apple event objects of each class. Most word-processing applications can specify the same object accessor function as well as the same token descriptor type for Apple event objects of these four classes, in which case the code shown in Listing 2-5 can be altered as shown in Listing 2-6.
  2974. Listing 2-6    Adding entries to an application’s object accessor dispatch table for one object accessor function that locates elements of different object classes in containers identified by tokens of the same descriptor type
  2975. myErr := AEInstallObjectAccessor(cText, typeMyText, 
  2976.                                             @MyFindTextObjectAccessor,
  2977.                                             0, FALSE);
  2978. IF myErr <> noErr THEN DoError(myErr);
  2979. myErr := AEInstallObjectAccessor(cWord, typeMyText, 
  2980.                                             @MyFindTextObjectAccessor,
  2981.                                             0, FALSE);
  2982. IF myErr <> noErr THEN DoError(myErr);
  2983. myErr := AEInstallObjectAccessor(cItem, typeMyText, 
  2984.                                             @MyFindTextObjectAccessor,
  2985.                                             0, FALSE);
  2986. IF myErr <> noErr THEN DoError(myErr);
  2987. myErr := AEInstallObjectAccessor(cChar, typeMyText, 
  2988.                                             @MyFindTextObjectAccessor,
  2989.                                             0, FALSE);
  2990. IF myErr <> noErr THEN DoError(myErr);    
  2991. In some situations you may want to write different object accessor functions to locate Apple event objects of the same object class that can be located in containers identified by tokens of different descriptor types. For example, the code in Listing 2-7 installs two different object accessor functions: one that finds a word in a container identified by a token of type typeMyTextToken, and one that finds a word in a container identified by a token of typeMyGraphicTextToken.
  2992. Listing 2-7    Adding entries to an application’s object accessor dispatch table for object accessor functions that locate elements of the same object class in containers identified by tokens of different descriptor types
  2993. myErr := AEInstallObjectAccessor(cWord, typeMyTextToken, 
  2994.                                             @MyFindTextObjectAccessor,
  2995.                                             0, FALSE);
  2996. IF myErr <> noErr THEN DoError(myErr);
  2997. myErr := AEInstallObjectAccessor(cWord, typeMyGraphicTextToken, 
  2998.                                             @MyFindGrphcTextObjectAccessor,
  2999.                                             0, FALSE);
  3000. IF myErr <> noErr THEN DoError(myErr);
  3001. Every application must provide one or more object accessor functions that can find Apple event objects in the default container, which is always identified by a token of descriptor type typeNull. Listing 2-8 demonstrates how to add entries to your application’s object accessor dispatch table for the object classes cDocument and cWindow. The container for each of these classes is identified by a token of descriptor type typeNull, which specifies an application’s default container.
  3002. Listing 2-8    Adding entries to an application’s object accessor dispatch table for object accessor functions that locate Apple event objects of different object classes in the default container
  3003. myErr := AEInstallObjectAccessor(cWindow, typeNull, 
  3004.                                             @MyFindWindowObjectAccessor,
  3005.                                             0, FALSE);
  3006. IF myErr <> noErr THEN DoError(myErr);
  3007. myErr := AEInstallObjectAccessor(cDocument, typeNull, 
  3008.                                             @MyFindDocumentObjectAccessor,
  3009.                                             0, FALSE);
  3010. IF myErr <> noErr THEN DoError(myErr);
  3011. For any entry in your object accessor dispatch table, you can specify a wildcard value for the object class, a wildcard value for the descriptor type of the token used to identify the container, or both. You specify a wildcard by supplying the typeWildCard constant when installing an entry into the object accessor dispatch table. A wildcard value matches all possible values.
  3012. For example, if you specify typeWildCard as the first parameter and typeMyToken as the second parameter for the AEInstallObjectAccessor function, the Apple Event Manager calls the object accessor function that you specify in the third parameter when resolving Apple event objects of any object class in containers identified by tokens of the typeMyToken descriptor type.
  3013. If you specify cText as the first parameter and typeWildCard as the second parameter for the AEInstallObjectAccessor function, the Apple Event Manager calls the object accessor function that you specify in the third parameter when resolving Apple event objects of the object class cText in containers identified by tokens of any descriptor type. 
  3014. If you specify typeWildCard as the first parameter and typeWildCard as the second parameter for the AEInstallObjectAccessor function, the Apple Event Manager calls the object accessor function that you specify in the third parameter when resolving Apple event objects of any object class in containers identified by tokens of any descriptor type.
  3015. If an object accessor dispatch table contains one entry for a specific object class and a specific token descriptor type, and another entry that is identical except that it specifies a wildcard value for either the object class or the token descriptor type, the Apple Event Manager will dispatch the more specific entry. For example, if an object accessor dispatch table includes one entry that specifies the object class as cWord and the token descriptor type as typeMyTextToken, and another entry that specifies the object class as cWord and the token descriptor type as typeWildCard, the Apple Event Manager will dispatch the object accessor function associated with the entry that specifies typeMyTextToken.
  3016. Installing Object Accessor Functions That Find Properties
  3017. The Apple event object to which a property belongs is that property’s container. You should add entries to your application’s object accessor dispatch table that specify object accessor functions for finding properties in containers identified by tokens of various descriptor types. Object specifier records do not specify a property’s specific object class; instead, they specify the constant cProperty as the class ID for any property. Similarly, you should specify the constant cProperty as the object class for an object accessor function that can find any property of a container identified by a token of a given descriptor type. If you need to install different object accessor routines for finding properties of Apple event objects that belong to different object classes, you must use different descriptor types for the tokens that represent those Apple event objects. 
  3018. For example, to specify an object accessor function that locates properties of Apple event objects identified by tokens of descriptor type typeMyToken, you can add a single entry to the object accessor dispatch table:
  3019. myErr := AEInstallObjectAccessor(cProperty, typeMyToken,
  3020.                                             @MyFindPropertyObjectAccessor,
  3021.                                             0, FALSE);
  3022. IF myErr <> noErr THEN DoError(myErr);
  3023. The code in this example adds an object accessor function to the application’s object accessor dispatch table that can find any property of any container identified by a token of descriptor type typeMyToken. If the second parameter were specified as typeWildCard, the MyFindPropertyObjectAccessor function would have to be capable of finding any property of any Apple event object in your application. 
  3024. Handling the Required Apple Events
  3025. This section describes the required Apple events—the Apple events your application must support to be 7.0-friendly—and the descriptor types for all parameters of the required Apple events. It also describes how to write the handlers for these events, and it provides sample code.
  3026. To support the required Apple events, you must set the necessary flags in the 'SIZE' resource of your application, install entries in your application’s Apple event dispatch table, add code to the event loop of your application to recognize high-level events, and call the AEProcessAppleEvent function, as described in “Accepting an Apple Event,” which begins on page 2-60, and “Installing Entries in the Apple Event Dispatch Tables,” which begins on page 2-63. You must also write handlers for each Apple event; this section describes how to write these handlers.
  3027. Required Apple Events
  3028. When a user opens or prints a file from the Finder, the Finder sets up the information your application uses to determine which files to open or print. In system software version 7.0, if your application supports high-level events, the Finder communicates this information to your application through the required Apple events. 
  3029. The Finder sends one of the required Apple events to your application to ask your application to open or print a list of documents, ask your application to perform the tasks required when a user opens it without opening or printing any documents, or inform your application that the Finder is about to terminate it.
  3030. These are the required Apple events:
  3031. Apple event        Requested action
  3032. Open Application        Perform tasks your application normally performs
  3033.         when a user opens your application without opening 
  3034.         or printing any documents
  3035. Open Documents        Open the specified documents 
  3036. Print Documents        Print the specified documents
  3037. Quit Application        Perform tasks—such as releasing memory, requesting 
  3038.         the user to save documents, and so on—associated 
  3039.         with quitting; the Finder sends this event to an 
  3040.         application immediately after sending it a Print 
  3041.         Documents event (unless the application was already 
  3042.         open) or if the user chooses Restart or Shut Down 
  3043.         from the Finder’s Special menu 
  3044. The Finder uses the required Apple events as part of the new mechanisms in system software version 7.0 for launching and terminating applications. This new method of communicating Finder information to your application replaces the mechanisms used in earlier versions of system software.
  3045. Applications that do not support high-level events can still use the CountAppFiles, GetAppFiles, and ClrAppFiles procedures (or the GetAppParms procedure) to get the Finder information. See the chapter “The Segment Loader” in Inside Macintosh: Operating System for information on these routines. To make your application 7.0-friendly and compatible with earlier versions of system software, it must support both the old and new mechanisms.
  3046. Use the Gestalt function to determine whether the Apple Event Manager is present. If it is and the isHighLevelEventAware flag is set in your application’s 'SIZE' resource, your application receives the Finder information through the required Apple events. 
  3047. If your application accepts high-level events, it must be able to process the four required Apple events—Open Application, Open Documents, Print Documents, or Quit Application—that the Finder sends in response to actions that the user performs from the desktop.
  3048. Your application receives the required Apple events from the Finder in these situations:
  3049. n    If your application is not open and the user opens your application from the Finder without opening or printing any documents, the Finder launches your application and sends it the Open Application event.
  3050. n    If your application is not open and the user opens one of your application’s documents from the Finder, the Finder launches your application and sends it the Open Documents event.
  3051. n    If your application is not open and the user prints one of your application’s documents from the Finder, the Finder launches your application and sends it the Print Documents event. Your application should print the selected documents and remain open until it receives a Quit event from the Finder.
  3052. n    If your application is open and the user opens or prints any of your application’s documents from the Finder, the Finder sends your application the Open Documents or Print Documents event.
  3053. n    If your application is open and the user chooses Restart or Shut Down from the Finder’s Special menu, the Finder sends your application the Quit event.
  3054. This section describes the required Apple events as they are sent by the Finder. When sent by other applications or processes, these same Apple events—which are among the core Apple events described in the Apple Event Registry: Standard Suites—can include optional parameters not listed here. To be 7.0-friendly, your application only needs to handle the required parameters that are described in this section.<36pt\>\x12 <8bat\>u
  3055. Upon receiving any of the required Apple events, your application should perform the action requested by the event. Here is a summary of the contents of the required events and the actions they request applications to perform:
  3056. Open Application—perform tasks associated with opening an application 
  3057. Event class        kCoreEventClass
  3058. Event ID        kAEOpenApplication
  3059. Parameters        None
  3060. Requested action        Perform any tasks—such as opening an untitled 
  3061.         document window—that you would normally 
  3062.         perform when a user opens your application without 
  3063.         opening or printing any documents.
  3064. Open Documents—open the specified documents
  3065. Event class        kCoreEventClass
  3066. Event ID        kAEOpenDocuments
  3067. Required parameter
  3068.     Keyword:    keyDirectObject
  3069.     Descriptor type:    typeAEList
  3070.     Data:    A list of alias records for the documents to be opened
  3071. Requested action        Open the documents specified in the                                                 
  3072.         keyDirectObject parameter.
  3073. Print Documents—print the specified documents
  3074. Event class        kCoreEventClass
  3075. Event ID        kAEPrintDocuments
  3076. Required parameter
  3077.     Keyword:    keyDirectObject
  3078.     Descriptor type:    typeAEList
  3079.     Data:    A list of alias records for the documents to be printed
  3080. Requested action        Print the documents specified in the 
  3081.         keyDirectObject parameter without opening 
  3082.         windows for the documents. 
  3083. Quit Application—perform tasks associated with quitting
  3084. Event class        kCoreEventClass
  3085. Event ID        kAEQuitApplication
  3086. Parameters        None
  3087. Requested action        Perform any tasks that your application would 
  3088.         normally perform when the user chooses Quit. Such 
  3089.         tasks typically include asking the user whether to save
  3090.         save documents that have been changed. When
  3091.         appropriate, the Finder sends this event to an 
  3092.         application immediately after sending it a Print 
  3093.         Documents event (unless the application was already 
  3094.         open) or if the user chooses Restart or Shut Down 
  3095.         from the Finder’s Special menu.
  3096. Your application needs to recognize only two descriptor types to handle the required Apple events: descriptor lists and alias records. The Open Documents event and Print Documents event use descriptor lists to store a list of documents to open. Each document is specified as an alias record in the descriptor list. 
  3097. You can retrieve the data that specifies the document to open as an alias record, or you can request that the Apple Event Manager coerce the alias record to a file system specification (FSSpec) record. The file system specification record provides a standard method of identifying files in version 7.0. See the chapter “The File Manager” in Inside Macintosh: Operating System for a complete description of how to specify files using file system specification records.
  3098. Handling the Open Application Event
  3099. When the user opens your application, the Finder uses the Process Manager to launch your application. On startup, your application typically performs any needed initialization, and then begins to process events. If your application supports high-level events, and if the user (or a script) opens your application without selecting any documents to open or print, your application receives the Open Application event.
  3100. To handle the Open Application event, your application should do just what the user expects it to do when it is opened. For example, your application might open a new untitled window in response to an Open Application event.
  3101. Listing 2-9 shows a handler that processes the Open Application event. This handler first calls an application-defined function called MyGotRequiredParams. This function checks to see if the Apple event contains any required parameters. By definition, the Open Application event should not contain any required parameters so, if the Apple event does contain any, the handler returns an error. Otherwise the handler opens a new document window.
  3102. A handler for the Open Application event
  3103. FUNCTION MyHandleOApp (theAppleEvent,reply: AppleEvent; 
  3104.                                 handlerRefcon: LongInt): OSErr;
  3105. VAR
  3106.     myErr: OSErr;
  3107. BEGIN
  3108.     myErr := MyGotRequiredParams(theAppleEvent);
  3109.     IF myErr <> noErr THEN
  3110.         MyHandleOApp := myErr
  3111.     ELSE
  3112.     BEGIN
  3113.         DoNew;
  3114.         MyHandleOApp := noErr;
  3115.     END;
  3116. END;
  3117. For a description of the MyGotRequiredParams function, see Listing 2-15 on page 2-95. For information about the reply and handlerRefcon parameters for an Apple event handler, see “Writing Apple Event Handlers” on page 2-93.
  3118. Handling the Open Documents Event
  3119. To handle the Open Documents event, your application should open the documents that the Open Documents event specifies in its direct parameter. Your application extracts this information and then opens the specified documents.
  3120. Listing 2-10 shows a handler for the Open Documents event. The handler illustrates how to open the documents referred to in the direct parameter.
  3121. A handler for the Open Documents event
  3122. FUNCTION MyHandleODoc (theAppleEvent,reply: AppleEvent;
  3123.                                    handlerRefcon: LongInt): OSErr;
  3124. VAR
  3125.     myFSS:                              FSSpec;
  3126.     docList:                              AEDescList;
  3127.     myErr:                              OSErr;
  3128.     index, itemsInList:                            LongInt;
  3129.     actualSize:                              Size;
  3130.     keywd:                              AEKeyword;
  3131.     returnedType:                              DescType;
  3132. BEGIN
  3133.     {get the direct parameter--a descriptor list--and put it }
  3134.     { into docList}
  3135.     myErr := AEGetParamDesc(theAppleEvent, keyDirectObject,
  3136.                                     typeAEList, docList);
  3137.     IF myErr <> noErr THEN DoError(myErr);
  3138.     {check for missing required parameters}
  3139.     myErr := MyGotRequiredParams(theAppleEvent);
  3140.     IF myErr <> noErr THEN         {an error occurred}
  3141.         BEGIN                            {do the necessary error handling}
  3142.             myErr := AEDisposeDesc(docList);
  3143.             MyHandleODoc := myErr;
  3144.             Exit(MyHandleODoc);
  3145.         END;
  3146.     {count the number of descriptor records in the list}
  3147.     myErr := AECountItems (docList,itemsInList);
  3148.     {now get each descriptor record from the list, coerce }
  3149.     { the returned data to an FSSpec record, and open the }
  3150.     { associated file}
  3151.     FOR index := 1 TO itemsInList DO
  3152.         BEGIN
  3153.             myErr := AEGetNthPtr(docList, index, typeFSS, keywd, 
  3154.                                     returnedType, @myFSS, Sizeof(myFSS), 
  3155.                                     actualSize);
  3156.             IF myErr <> noErr THEN DoError(myErr);
  3157.             myErr := MyOpenFile(myFSS);
  3158.             IF myErr <> noErr THEN DoError(myErr);
  3159.         END;
  3160.     myErr := AEDisposeDesc(docList);
  3161.     MyHandleODoc := noErr;
  3162. END;
  3163. The handler in Listing 2-10 first uses the AEGetParamDesc function to get the direct parameter (specified by the keyDirectObject keyword) out of the Apple event. The handler requests that AEGetParamDesc return a descriptor list in the docList variable. The handler then checks to make sure that it has retrieved all of the required parameters by calling the MyGotRequiredParams function. (See Listing 2-15 on page 2-95 for a description of this function.)
  3164. Once the handler has retrieved the descriptor list from the Apple event, it uses AECountItems to count the number of descriptors in the list. Using the returned number as an index, the handler can get the data of each descriptor record in the list. This handler requests that the AEGetNthPtr function coerce the data in the descriptor record to a file system specification record. The handler can then use the file system specification record as a parameter to its own routine for opening files.
  3165. For more information on the AEGetParamDesc function, see “Getting Data Out of an Apple Event Parameter” on page 2-87. For more information on the AEGetNthPtr and AECountItems functions, see “Getting Data Out of a Descriptor List” on page 2-91.
  3166. After extracting the file system specification record that describes the document to open, your application can use this record to open the file. For example, in Listing 2-10, the code passes the file system specification record to its routine for opening files, the MyOpenFile function. 
  3167. The MyOpenFile function should be designed so that it can be called both in response to the Open Documents event and to events generated by the user. For example, when the user chooses Open from the File menu, the code that handles the mouse-down event uses the StandardGetFile procedure to let the user choose a file; it then calls MyOpenFile, passing the file system specification record returned by StandardGetFile. By isolating code that performs a requested action from code that interacts with the user, you can easily adapt your application to handle Apple events that request the same action. 
  3168. Note that your handler should use the AEDisposeDesc function to dispose of the descriptor list when your handler no longer requires the data in it. Your handler should also return a result code.
  3169. Handling the Print Documents Event
  3170. To handle the Print Documents event, your application should print the documents that the Print Documents event specifies in its direct parameter. Your application extracts this information and then prints the specified documents. Your application should not open any windows for the documents. Also note that your application should remain open after processing the Print Documents event; when appropriate, the Finder sends your application a Quit Application event immediately after sending it a Print Documents event.
  3171. Listing 2-11 shows a handler for the Print Documents event. This handler is similar to the handler for the Open Documents event. The code illustrates how to print the documents referred to in the direct parameter.
  3172. A handler for the Print Documents event
  3173. FUNCTION MyHandlePDoc (theAppleEvent,reply: AppleEvent;
  3174.                                handlerRefcon: LongInt): OSErr;
  3175. VAR
  3176.     myFSS:                            FSSpec;
  3177.     docList:                             AEDescList;
  3178.     myErr:                             OSErr;
  3179.     index, itemsInList:                            LongInt;
  3180.     actualSize:                             Size;
  3181.     keywd:                             AEKeyword;
  3182.     returnedType:                             DescType;
  3183. BEGIN
  3184.     {get the direct parameter--a descriptor list--and put it }
  3185.     { into docList}
  3186.     myErr := AEGetParamDesc(theAppleEvent, keyDirectObject,                     
  3187.                                     typeAEList, docList);
  3188.     IF myErr <> noErr THEN DoError(myErr);
  3189.     {check for missing required parameters}
  3190.     myErr := MyGotRequiredParams(theAppleEvent);
  3191.     IF myErr <> noErr THEN {an error occurred}
  3192.         BEGIN
  3193.             {do the necessary error handling}
  3194.             myErr := AEDisposeDesc(docList);
  3195.             MyHandlePDoc := myErr;
  3196.             Exit(MyHandlePDoc);
  3197.         END;
  3198.     {count the number of descriptor records in the list}
  3199.     myErr := AECountItems (docList,itemsInList);
  3200.     {now get each descriptor record from the list, coerce }
  3201.     { the returned data to an FSSpec record, and print the }
  3202.     { associated file}
  3203.     FOR index := 1 TO itemsInList DO
  3204.         BEGIN
  3205.         myErr := AEGetNthPtr(docList, index, typeFSS, keywd,                                             
  3206.                                     returnedType,     @myFSS, Sizeof(myFSS), 
  3207.                                     actualSize);
  3208.         IF myErr <> noErr THEN DoError(myErr);
  3209.         myErr := MyPrintFile(myFSS);
  3210.         IF myErr <> noErr THEN DoError(myErr);
  3211.         END;
  3212.     myErr := AEDisposeDesc(docList);
  3213.     MyHandlePDoc := noErr;
  3214. END;
  3215. Handling the Quit Application Event
  3216. To handle the Quit Application event, your application should take any actions that are necessary before it is terminated (such as saving any open documents). Listing 2-12 shows an example of a handler for the Quit Application event.
  3217. When appropriate, the Finder sends your application a Quit Application event immediately after a Print Documents event. The Finder also sends your application a Quit Application event if the user chooses Restart or Shut Down from the Finder’s Special menu. 
  3218. A handler for the Quit Application event
  3219. FUNCTION MyHandleQuit (theAppleEvent,reply: AppleEvent;
  3220.                                 handlerRefcon: LongInt): OSErr;
  3221. VAR
  3222.     userCanceled:                        Boolean;
  3223.     myErr:                        OSErr;
  3224. BEGIN
  3225.     {check for missing required parameters}
  3226.     myErr := MyGotRequiredParams(theAppleEvent);
  3227.     IF myErr <> noErr THEN {an error occurred}
  3228.         BEGIN
  3229.             {do the necessary error handling}
  3230.             MyHandleQuit := myErr;
  3231.             Exit (MyHandleQuit);
  3232.         END;
  3233.     userCanceled := MyPrepareToTerminate;
  3234.     IF userCanceled THEN
  3235.         MyHandleQuit := userCanceledErr
  3236.     ELSE
  3237.         MyHandleQuit := noErr;
  3238. END;
  3239. The handler in Listing 2-12 calls another function supplied by the application, the MyPrepareToTerminate function. This function saves the documents for any open windows and returns a Boolean value that indicates whether the Quit request was canceled by the user. This is another example of isolating code for interacting with the user from the code that performs the requested action. Structuring your application in this way allows your application to use the same routine when responding to a user event (such as choosing the Quit command from the File menu) or to the corresponding Apple event. (For a description of the MyGotRequiredParams function, see “Writing Apple Event Handlers,” which begins on page 2-93.)
  3240. When your application is ready to quit, it should call the ExitToShell procedure from the main event loop, not from your handler for the Quit Application event. Your application should quit only after the handler returns noErr as its function result.
  3241. Handling Apple Events Sent by the Edition Manager
  3242. If your application provides publish and subscribe capabilities, it should handle the Apple events sent by the Edition Manager in addition to the required Apple events. Your application should also handle the Create Publisher event, which is described in the next section.
  3243. The Edition Manager sends your application Apple events to communicate information about the publishers and subscribers in your application’s documents. Specifically, the Edition Manager uses Apple events to notify your application 
  3244. n    when the information in an edition is updated
  3245. n    when your application needs to write the data from a publisher to an edition
  3246. n    when your application should locate a particular publisher and scroll through the document to that location
  3247. The Apple events sent by the Edition Manager to your application are the Section Read event, Section Write event, and Section Scroll event.
  3248. Section Read—read information into the specified section
  3249. Event class        SectionEventMsgClass
  3250. Event ID        SectionReadMsgID
  3251. Required parameter
  3252.     Keyword:    keyDirectObject
  3253.     Descriptor type:    typeSectionH
  3254.     Data:    A handle to the section record of the subscriber 
  3255.         whose edition contains updated information
  3256. Requested action        Update the subscriber with the new information from 
  3257.         the edition.
  3258. Section Write—write the specified section to an edition
  3259. Event class        SectionEventMsgClass
  3260. Event ID        SectionWriteMsgID
  3261. Required parameter
  3262.     Keyword:    keyDirectObject
  3263.     Descriptor type:    typeSectionH
  3264.     Data:    A handle to the section record of the publisher
  3265. Requested action        Write the publisher’s data to its edition.
  3266. Section Scroll—scroll through the document to the specified section
  3267. Event class        SectionEventMsgClass
  3268. Event ID        SectionScrollMsgID
  3269. Required parameter
  3270.     Keyword:    keyDirectObject
  3271.     Descriptor type:    typeSectionH
  3272.     Data:    A handle to the section record of the publisher to 
  3273.         scroll to
  3274. Requested actio    n    Scroll the document to the publisher identified by the 
  3275.         specified section record. 
  3276. See the chapter “The Edition Manager” in this book for details on how your application should respond to these events.
  3277. Handling the Create Publisher Event
  3278. If your application supports publish and subscribe capabilities, it should also handle the Create Publisher event.
  3279. Create Publisher—create a publisher
  3280. Event class        kAEMiscStdSuite
  3281. Event ID        kAECreatePublisher
  3282. Required parameter        None
  3283. Optional parameter
  3284.     Keyword:    keyDirectObject
  3285.     Descriptor type:    typeObjectSpecifier
  3286.     Data:    An object specifier record that specifies the Apple 
  3287.         event object or objects to publish. If this parameter
  3288.         is omitted, publish the current selection.
  3289. Optional parameter
  3290.     Keyword:    keyAEEditionFileLoc
  3291.     Descriptor type:    typeAlias
  3292.     Data:    An alias record that contains the location of the 
  3293.         edition container to create. If this parameter is 
  3294.         omitted, use the default edition container.
  3295. Requested action        Create a publisher for the specified data using the 
  3296.         specified location for the edition container. If the 
  3297.         data isn’t specified, publish the current selection. If 
  3298.         the location of the edition isn’t specified, use the 
  3299.         default location.
  3300. When your application receives the Create Publisher event, it should create a publisher and write the publisher’s data to an edition. The data of the publisher, and the location and name of the edition, are defined by the Apple event. If the Create Publisher event includes a keyDirectObject parameter, then your application should publish the data contained in the parameter. If the keyDirectObject parameter is missing, then your application should publish the current selection. If the document doesn’t have a current selection, your handler for the event should return a nonzero result code.
  3301. If the Create Publisher event includes a keyAEEditionFileLoc parameter, your application should use the location and name contained in the parameter as the default location and name of the edition. If the keyAEEditionFileLoc parameter is missing, your application should use the default location and name your application normally uses to specify the edition container.
  3302. Listing 2-13 shows a handler for the Create Publisher event. This handler checks for the keyDirectObject parameter and the keyAEEditionFileLoc parameter. If either of these is not specified, the handler uses default values. The handler uses the application-defined function DoNewPublisher function to create the publisher and its edition, create a section record, and update other data structures associated with the document. See the chapter “The Edition Manager” for an example of the DoNewPublisher function.
  3303. Note that the handler uses the AEInteractWithUser function to determine whether user interaction is allowed. If user interaction is allowed, the handler sets the promptForDialog variable to TRUE, indicating that the DoNewPublisher function should display the publisher dialog box. If user interaction is not allowed, the handler sets the promptForDialog variable to FALSE, and the DoNewPublisher function does not prompt the user for the location or name of the edition.
  3304. A handler for the Create Publisher event
  3305. FUNCTION MyHandleCreatePublisherEvent (theAppleEvent,reply: 
  3306.                                                     AppleEvent; 
  3307.                                                     handlerRefcon: LongInt): 
  3308.                                                     OSErr;
  3309. VAR        myErr:                                 OSErr;
  3310.     returnedType:                                DescType;
  3311.     thePublisherDataDesc:                                AEDesc;
  3312.     actualSize:                                 LongInt;
  3313.     promptForDialog:                                Boolean;
  3314.     thisDocument:                                 MyDocumentInfoPtr;
  3315.     preview:                                 Handle; 
  3316.     previewFormat:                                 FormatType; 
  3317.     defaultLocation:                                 EditionContainerSpec;
  3318.  
  3319. BEGIN
  3320.     MyGetDocumentPtr(thisDocument);
  3321.     myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, 
  3322.             typeObjectSpecifier, thePublisherDataDesc);
  3323.     CASE myErr OF
  3324.         errAEDescNotFound: 
  3325.         BEGIN
  3326.             {use the current selection as the publisher and set up }
  3327.             { info for later when DoNewPublisher displays preview}
  3328.             preview := MyGetPreviewForSelection(thisDocument);
  3329.             previewFormat := 'TEXT';
  3330.         END;
  3331.         noErr: 
  3332.             {use the data in keyDirectObject parameter as the }
  3333.             { publisher (which is returned in the }
  3334.             { thePublisherDataDesc variable), and set up info for }
  3335.             { later when DoNewPublisher displays preview}
  3336.  
  3337.             MySetInfoForPreview(thePublisherDataDesc, thisDocument, 
  3338.                                        preview, previewFormat);
  3339.         OTHERWISE
  3340.             DoError(myErr);
  3341.     END; {of CASE}
  3342.     myErr := AEGetParamPtr(theAppleEvent, keyAEEditionFileLoc, 
  3343.                                   typeFSS, returnedType, 
  3344.                                   @defaultLocation.theFile,
  3345.                                   SizeOf(FSSpec), actualSize);
  3346.  
  3347.     CASE myErr OF
  3348.         errAEDescNotFound: 
  3349.             {use the default location as the edition container}
  3350.                 myErr := MyGetDefaultEditionSpec(thisDocument, 
  3351.                                                         defaultLocation);
  3352.         noErr: 
  3353.         BEGIN                        {the keyAEEditionFileLoc parameter }
  3354.                                  { contained a default location}
  3355.             defaultLocation.thePart := kPartsNotUsed;
  3356.             defaultLocation.theFileScript := smSystemScript;
  3357.         END;
  3358.         OTHERWISE
  3359.             DoError(myErr);
  3360.     END; {of CASE}
  3361.     myErr := MyGotRequiredParams(theAppleEvent);
  3362.     IF myErr <> noErr THEN
  3363.     BEGIN
  3364.         {handle the error appropriately}
  3365.         MyHandleCreatePublisherEvent := myErr;
  3366.     END;
  3367.     myErr := AEInteractWithUser(kAEDefaultTimeout, NIL, 
  3368.                                             @MyIdleFunction);
  3369.     IF myErr = noErr THEN promptForDialog := TRUE
  3370.     ELSE     
  3371.     promptForDialog := FALSE
  3372.     myErr := DoNewPublisher(thisDocument, promptForDialog, 
  3373.                           preview, previewFormat, defaultLocation);
  3374.     {add keyErrorNumber and keyErrorString parameters if desired}
  3375.     MyHandleCreatePublisherEvent := myErr;
  3376. END;
  3377. Getting Data Out of an Apple Event
  3378. The Apple Event Manager stores the parameters and attributes of an Apple event in a format that is internal to the Apple Event Manager. You use Apple Event Manager functions to retrieve the data from an Apple event and return it to your application in a format your application can use.
  3379. The Apple Event Manager provides functions that retrieve data from Apple event parameters and attributes. Most of these functions are available in two forms: one that returns the desired data in a specified buffer and one that returns a descriptor record containing the same data. For example, the AEGetParamPtr function uses a specified buffer to return the data contained in an Apple event parameter, and the AEGetParamDesc function returns the descriptor record for a specified parameter. 
  3380. You can also use Apple Event Manager functions to get data out of descriptor records, descriptor lists, and AE records. You use similar functions to put data into descriptor records, descriptor lists, and AE records.
  3381. When your handler receives an Apple event, you typically use the AEGetParamPtr, AEGetAttributePtr, AEGetParamDesc, or AEGetAttributeDesc function to get the data out of the Apple event.
  3382. Some Apple Event Manager functions let your application request that the data be returned using any descriptor type, even if it is different from the original descriptor type. If the original data is of a different descriptor type, the Apple Event Manager attempts to coerce the data to the requested descriptor type. 
  3383. For example, the AEGetParamPtr function lets you specify the desired descriptor type of the resulting data as follows:
  3384. VAR
  3385.     theAppleEvent:                        AppleEvent;
  3386.     returnedType:                         DescType;
  3387.     multResult:                        LongInt;
  3388.     actualSize:                         Size;
  3389.     myErr:                         OSErr;
  3390. myErr := AEGetParamPtr(theAppleEvent, keyMultResult, 
  3391.                               typeLongInteger, returnedType, 
  3392.                               @multResult, SizeOf(multResult),                                     
  3393.                               actualSize);
  3394. In this example, the desired type is specified in the third parameter by the typeLongInteger descriptor type. This requests that the Apple Event Manager coerce the data to a long integer if it is not already of this type. 
  3395. To ensure that no coercion is performed and that the descriptor type of the result is of the same type as the original, you can specify typeWildCard for the desired descriptor type.
  3396. The Apple Event Manager returns the descriptor type of the resulting data in the returnedType parameter. This is useful information when you specify typeWildCard as the desired descriptor type; you can determine the descriptor type of the resulting data by examining this parameter.
  3397. The Apple Event Manager can coerce many different types of data. For example, the Apple Event Manager can convert alias records to file system specification records, integers to Boolean data types, and characters to numeric data types, in addition to other data type conversions. For a complete list of the data types for which the Apple Event Manager provides coercion handling, see Table 2-1 on page 2-156.
  3398. To perform data coercions that the Apple Event Manager doesn’t perform, you can provide your own coercion handlers. See “Writing and Installing Coercion Handlers,” which begins on page 2-153, for information on providing your own coercion handlers.
  3399. Apple event parameters are keyword-specified descriptor records. You can use AEGetParamDesc to get the descriptor record of a parameter, or you can use AEGetParamPtr to get the data out of the descriptor record of a parameter. If an Apple event parameter consists of an object specifier record, you can use AEResolve and your own object accessor functions to resolve the object specifier record—that is, to locate the Apple event object it describes. For more information about AEResolve and object accessor functions, see “Writing Object Accessor Functions,” which begins on page 2-157. Attributes are also keyword-specified descriptor records, and you can use similar routines to get the descriptor record of an attribute or to get the data out of an attribute.
  3400. The following sections show how to use the AEGetParamPtr, AEGetAttributePtr, AEGetParamDesc, or AEGetAttributeDesc function to get the data out of an Apple event.
  3401. Getting Data Out of an Apple Event Parameter
  3402. You can use the AEGetParamPtr or AEGetParamDesc function to get the data out of an Apple event parameter. Use the AEGetParamPtr function (or the AEGetKeyPtr function, which works the same way) to return the data contained in a parameter. Use the AEGetParamDesc function when you need to get the descriptor record of a parameter or to extract the descriptor list from a parameter.
  3403. For example, you use an Apple Event Manager function to get the data out of a Section Read event. The Edition Manager sends your application a Section Read event to tell your application to read updated information from an edition into the specified subscriber. The direct parameter of the Apple event contains a handle to the section record of the subscriber. You can use the AEGetParamPtr function to get the data out of the Apple event.
  3404. You specify the Apple event that contains the desired parameter, the keyword of the desired parameter, the descriptor type the function should use to return the data, a buffer to store the data, and the size of this buffer as parameters to the AEGetParamPtr function. The AEGetParamPtr function returns the descriptor type of the resulting data and the actual size of the data, and it places the requested data in the specified buffer.
  3405. VAR
  3406.     sectionH:                        SectionHandle;
  3407.     theAppleEvent:                        AppleEvent;
  3408.     returnedType:                         DescType;
  3409.     actualSize:                         Size;
  3410.     myErr:                         OSErr;
  3411. myErr := AEGetParamPtr(theAppleEvent, keyDirectObject, 
  3412.                               typeSectionH, returnedType, @sectionH, 
  3413.                               SizeOf(sectionH), actualSize);
  3414. In this example, the keyDirectObject keyword specifies that the AEGetParamPtr function should extract information from the direct parameter; AEGetParamPtr returns the data in the buffer specified by the sectionH variable. 
  3415. You can request that the Apple Event Manager return the data using the descriptor type of the original data or you can request that the Apple Event Manager coerce the data into a descriptor type that is different from the original. You can specify the desired descriptor type as typeWildCard if you don’t want any coercion performed—in which case, the AEGetParamPtr function returns the original descriptor type of the parameter.
  3416. The typeSectionH descriptor type specifies that the returned data should be coerced to a handle to a section record. You can use the information returned in the sectionH variable to identify the subscriber and read in the information from the edition.
  3417. In this example, the AEGetParamPtr function returns in the returnedType variable the descriptor type of the resulting data. The descriptor type of the resulting data matches the requested descriptor type unless the Apple Event Manager wasn’t able to coerce the data to the specified descriptor type or you specified the desired descriptor type as typeWildCard. If the coercion fails, the Apple Event Manager returns the errAECoercionFail result code.
  3418. The AEGetParamPtr function returns the actual size of the data (that is, the size of coerced data, if any coercion was performed) returned in the actualSize variable. If the value returned in the actualSize variable is greater than the amount your application allocated for the buffer to hold the returned data, your application can increase the size of its buffer to this amount, and get the data again. You can also choose to use the AEGetParamDesc function when your application doesn’t know the size of the data.
  3419. In general, use the AEGetParamPtr function to extract data that is of fixed length or known maximum length, and the AEGetParamDesc function to extract data that is of variable length. The AEGetParamDesc function returns the descriptor record for a Apple event parameter. This function is useful, for example, for extracting a descriptor list from a parameter.
  3420. You specify the Apple event that contains the desired parameter, the keyword of the desired parameter, the descriptor type the function should use to return the descriptor record, and a buffer to store the returned descriptor record as parameters to the AEGetParamDesc function. The AEGetParamDesc function returns the descriptor record using the specified descriptor type. 
  3421. For example, the direct parameter of the Open Documents event contains a descriptor list that specifies the documents to open. You can use the AEGetParamDesc function to get the descriptor list out of the direct parameter.
  3422. VAR
  3423.     docList:                        AEDescList;
  3424.     theAppleEvent:                        AppleEvent;
  3425.     myErr:                         OSErr;
  3426. myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, 
  3427.                                 typeAEList, docList);
  3428. In this example, the Apple event specified by the variable theAppleEvent contains the desired parameter. The keyDirectObject keyword specifies that the AEGetParamDesc function should get the descriptor record of the direct parameter. The typeAEList descriptor type specifies that the descriptor record should be returned as a descriptor list. In this example, the AEGetParamDesc function returns a descriptor list in the docList variable.
  3429. The descriptor list contains a list of descriptor records. To get the descriptor records and their data out of a descriptor list, use the AECountItems function to find the number of descriptor records in the list, and then make repetitive calls to the AEGetNthPtr function to get the data out of each descriptor record. See “Getting Data Out of a Descriptor List” on page 2-91 for more information.
  3430. Note that the AEGetParamDesc function copies the descriptor record from the parameter. When you’re done with a descriptor record that you obtained from AEGetParamDesc, you must dispose of it by calling the AEDisposeDesc function.
  3431. If an Apple event parameter consists of an object specifier record, you can use AEResolve to resolve the object specifier record (that is, locate the Apple event object it describes), as explained in “Resolving Object Specifier Records” on page 2-53.
  3432. Getting Data Out of an Attribute
  3433. You can use the AEGetAttributePtr or AEGetAttributeDesc function to get the data out of the attributes of an Apple event.
  3434. You specify the Apple event that contains the desired attribute, the keyword of the desired attribute, the descriptor type the function should use to return the data, a buffer to store the data, and the size of this buffer as parameters to the AEGetAttributePtr function. The AEGetAttributePtr function returns the descriptor type of the returned data and the actual size of the data, and it places the requested data in the specified buffer.
  3435. For example, this code gets the data out of the keyEventSourceAttr attribute of an Apple event:
  3436. VAR
  3437.     theAppleEvent:                        AppleEvent;
  3438.     returnedType:                         DescType;
  3439.     sourceOfAE:                        Integer;
  3440.     actualSize:                        Size;
  3441.     myErr:                         OSErr;
  3442. myErr := AEGetAttributePtr(theAppleEvent, keyEventSourceAttr, 
  3443.                                       typeShortInteger, returnedType, 
  3444.                                     @sourceOfAE, SizeOf(sourceOfAE), 
  3445.                                     actualSize);
  3446. The keyEventSourceAttr keyword specifies the attribute from which to get the data. The typeShortInteger descriptor type specifies that the data should be returned as a short integer; the returnedType variable contains the actual descriptor type that is returned. You also must specify a buffer to hold the returned data and specify the size of this buffer. If the data is not already a short integer, the Apple Event Manager will coerce it before returning it. The AEGetAttributePtr function returns the actual size of the data returned in the actualSize variable after coercion has taken place. You can check this value to make sure you got all the data.
  3447. As with the AEGetParamPtr function, you can request that AEGetAttributePtr return the data using the descriptor type of the original data, or you can request that the Apple Event Manager coerce the data into a descriptor type that is different from the original. 
  3448. In this example, the AEGetAttributePtr function returns the requested data as a short integer in the sourceOfAE variable, and you can get information about the source of the Apple event by examining this value. You can test the returned value against the values defined by the data type AEEventSource:
  3449. TYPE AEEventSource = (kAEUnknownSource, kAEDirectCall, 
  3450.                                 kAESameProcess, kAELocalProcess, 
  3451.                                 kAERemoteProcess);
  3452. The constants defined by the data type AEEventSource have the following meanings:
  3453. Constant         Meaning
  3454. kAEUnknownSource        Source of Apple event unknown
  3455. kAEDirectCall        A direct call that bypassed the PPC Toolbox
  3456. kAESameProcess        Target application is also the source application
  3457. kAELocalProcess        Source application is another process on the same 
  3458.         computer as the target application
  3459. kAERemoteProcess        Source application is a process on a remote 
  3460.         computer on the network
  3461. The next example shows how to use the AEGetAttributePtr function to get data out of the keyMissedKeywordAttr attribute. After your handler extracts all known parameters from an Apple event, it should check whether the keyMissedKeywordAttr attribute exists. If it does, then your handler did not get all of the required parameters.
  3462. Note that if AEGetAttributePtr returns the errAEDescNotFound result code, then the keyMissedKeywordAttribute does not exist—which indicates that your application has extracted all of the required parameters. If AEGetAttributePtr returns noErr, then the keyMissedKeywordAttribute does exist—which indicates that your handler did not get all of the required parameters.
  3463. myErr := AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, 
  3464.                                     typeWildCard, returnedType, NIL, 0, 
  3465.                                     actualSize);
  3466. The data in the keyMissedKeywordAttr attribute contains the keyword of the first required parameter, if any, that your handler didn’t retrieve. If you want this data returned, specify a buffer to hold the data and specify the size of the buffer. Otherwise, as in this example, specify NIL as the buffer and 0 as the size of the buffer.
  3467. This example shows how to use the AEGetAttributePtr function to get the address of the sender of an Apple event from the keyAddressAttr attribute of the Apple event:
  3468. VAR
  3469.     theAppleEvent: AppleEvent;
  3470.     returnedType: DescType;
  3471.     addressOfAE: TargetID;
  3472.     actualSize: Size;
  3473.     myErr: OSErr
  3474.  
  3475. myErr := AEGetAttributePtr(theAppleEvent, keyAddressAttr, 
  3476.                                     typeTargetID, returnedType, 
  3477.                                     @addressOfAE, SizeOf(addressOfAE), 
  3478.                                     actualSize);
  3479. The keyAddressAttr keyword specifies the attribute to get the data from. The typeTargetID descriptor type specifies that the data should be returned as a target ID record; the returnedType variable contains the actual descriptor type that is returned. You can examine the address returned in the addressOfAE variable to determine the sender of the Apple event.
  3480. The target ID record returned in the addressOfAE variable contains the sender’s port name, port location, and session reference number. To get the process serial number for a process on the local machine, pass the port name returned in the target ID record to the GetProcessSerialNumberFromPortName function. You can then pass the process serial number to the GetProcessInformation function to find the creator signature for a given process.
  3481. For more information about target addresses, see “Specifying a Target Address” on page 2-116.
  3482. Getting Data Out of a Descriptor List
  3483. You can use the AECountItems function to count the number of items in a descriptor list, and you can use AEGetNthDesc or AEGetNthPtr to get a descriptor record or its data out of a descriptor list.
  3484. The Open Documents event contains a direct parameter that specifies the list of documents to open. The list of documents is contained in a descriptor list. After extracting the descriptor list from the parameter, you can determine the number of items in the list and then extract each descriptor record from the descriptor list. See Figure 2-8 on page 2-22 for a depiction of the Open Documents event.
  3485. For example, when your handler receives an Open Documents event, you can use the AEGetParamDesc function to return the direct parameter as a descriptor list. You can then use AECountItems to return the number of descriptor records in the list.
  3486. VAR
  3487.     theAppleEvent:                        AppleEvent;
  3488.     docList:                        AEDescList;
  3489.     itemsInList:                        LongInt;
  3490.     myErr:                        OSErr;
  3491. myErr := AEGetParamDesc(theAppleEvent, keyDirectObject,     
  3492.                                 typeAEList, docList);
  3493. myErr := AECountItems(docList, itemsInList);
  3494. The AEGetParamDesc function returns in the docList variable the descriptor list from the direct parameter of the Open Documents event. You specify this list to the AECountItems function.
  3495. You specify the descriptor list whose items you want to count in the first parameter to AECountItems. The Apple Event Manager returns the number of items in the list in the second parameter. When extracting the descriptor records from a list, you often use the number of items as a loop index. Here’s an example:
  3496. FOR index := 1 TO itemsInList DO
  3497.     BEGIN
  3498.     {for each descriptor record in the list, get its data}
  3499.     END;
  3500. The format of the descriptor records in a descriptor list is private to the Apple Event Manager. You must use the AEGetNthPtr or AEGetNthDesc function to extract descriptor records from a descriptor list.
  3501. You specify the descriptor list that contains the desired descriptor records and an index as parameters to the AEGetNthPtr function. The index represents a specific descriptor record in the descriptor list. AEGetNthPtr returns the data from the descriptor record represented by the specified index. 
  3502. You also specify the descriptor type the function should use to return the data, a buffer to store the data, and the size of this buffer. If the specified descriptor record exists, the AEGetNthPtr function returns the keyword of the parameter, the descriptor type of the returned data, and the actual size of the data, and it places the requested data in the specified buffer.
  3503. Here’s an example that uses the AEGetNthPtr function to extract an item from the descriptor list in the direct parameter of the Open Documents event. 
  3504. myErr := AEGetNthPtr(docList, index, typeFSS, keywd, 
  3505.                             returnedType, @myFSS, Sizeof(myFSS), 
  3506.                             actualSize);
  3507. The docList variable specifies the descriptor list from the direct parameter of the Open Documents event. The index variable specifies the index of the descriptor record to extract. You can use the typeFSS descriptor type, as in this example, to specify that the data be returned as a file system specification record. The Apple Event Manager automatically coerces the original data type of the descriptor record from an alias record to a file system specification record. The AEGetNthPtr function returns the keyword of the parameter in the keywd variable. The function returns in the returnedType variable the descriptor type of the resulting data. 
  3508. You specify a buffer to hold the desired data and the size (in bytes) of the buffer as parameters to the AEGetNthPtr function. In this example, the myFSS variable specifies the buffer. The function returns the actual size of the data in the actualSize variable. If this size is larger than the size of the buffer you provided, you know that you didn’t get all of the data for the descriptor record.
  3509. Listing 2-14 shows a more complete example of extracting the items from a descriptor list in the Open Documents event.
  3510. Extracting items from a descriptor list
  3511. VAR
  3512.     index:                        LongInt;
  3513.     itemsInList:                         LongInt;
  3514.     docList:                        AEDescList;
  3515.     keywd:                         AEKeyword;
  3516.     returnedType:                         DescType;
  3517.     myFSS:                        FSSpec;
  3518.     actualSize:                         Size;
  3519.     myErr:                         OSErr;
  3520.  
  3521. FOR index := 1 TO itemsInList DO
  3522.     BEGIN
  3523.         myErr := AEGetNthPtr(docList, index, typeFSS, keywd, 
  3524.                                     returnedType , @myFSS, Sizeof(myFSS), 
  3525.                                     actualSize);
  3526.         IF myErr <> noErr THEN DoError(myErr);
  3527.         myErr := MyOpenFile(@myFSS);
  3528.         IF myErr <> noErr THEN DoError(myErr);
  3529.     END;
  3530. myErr := AEDisposeDesc(docList); 
  3531. Writing Apple Event Handlers
  3532. For each Apple event your application supports, you must provide a function called an Apple event handler. The AEProcessAppleEvent function calls one of your Apple event handlers when it processes an Apple event. Your Apple event handlers should perform any action requested by the Apple event, add parameters to the reply Apple event if appropriate, and return a result code.
  3533. The Apple Event Manager uses dispatch tables to route Apple events to the appropriate Apple event handler. You must supply an Apple event handler for each entry in your application’s Apple event dispatch table. Each handler must be a function that uses this syntax:
  3534. FUNCTION MyEventHandler (theAppleEvent: AppleEvent; 
  3535.                                  reply: AppleEvent; 
  3536.                                  handlerRefcon: LongInt): OSErr; 
  3537. The parameter theAppleEvent is the Apple event to handle. Your handler uses Apple Event Manager functions to extract any parameters and attributes from the Apple event and then performs the necessary processing. The reply parameter is the default reply provided by the Apple Event Manager. (“Replying to an Apple Event” on page 2-96 describes how to add parameters to the default reply.) The handlerRefcon parameter is the reference constant stored in the Apple event dispatch table entry for the Apple event. Your handler should pass 0 in this parameter if your application does not use the reference constant.
  3538. You can use the reference constant for anything you wish. For example, if you want to handle several Apple events with one handler, you can install entries for each event in your application’s Apple event dispatch table that specify the same handler but different reference constants. Your handler can then use the reference constant to distinguish the different Apple events it handles.
  3539. After extracting all known parameters from the Apple event, every handler should determine whether the Apple event contains any further required parameters. Your handler can determine whether it retrieved all the required parameters by checking to see if the keyMissedKeywordAttr attribute exists. If the attribute exists, then your handler has not retrieved all the required parameters and should immediately return an error. If the attribute does not exist, then the Apple event does not contain any more required parameters, although it may contain additional optional parameters.
  3540. The Apple Event Manager determines which parameters are optional according to the keywords listed in the keyOptionalKeywordAttr attribute. The source application is responsible for adding keywords for any optional parameters to the keyOptionalKeywordAttr attribute, a source application can choose not to include the keyword for an Apple event parameter even if that parameter is listed in the Apple Event Registry: Standard Suites as an optional parameter. This has the effect of forcing the target application to treat the parameter as required for a particular Apple event. If the target application supports the optional parameter, it should handle the Apple event as the client application expects. If the target application does not support the optional parameter and checks whether it has received all the required parameters, it finds that there’s another parameter that the client application considered required, and should return the result code errAEEventNotHandled.  
  3541. Listing 2-15 shows a function that checks for a keyMissedKeywordAttr attribute. A handler calls this function after getting all the parameters it knows about from an Apple event.
  3542. A function that checks for a keyMissedKeywordAttr attribute
  3543. FUNCTION MyGotRequiredParams (theAppleEvent: AppleEvent): OSErr;
  3544. VAR
  3545.     returnedType:                        DescType;
  3546.     actualSize:                        Size;
  3547.     myErr:                        OSErr;
  3548. BEGIN
  3549.     myErr := AEGetAttributePtr(theAppleEvent, 
  3550.                                          keyMissedKeywordAttr, 
  3551.                                              typeWildCard, returnedType, 
  3552.                                          NIL, 0, actualSize);
  3553.     IF myErr = errAEDescNotFound THEN                                             {you got all the required }
  3554.                                                  { parameters}
  3555.         MyGotRequiredParams := noErr
  3556.     ELSE IF myErr = noErr THEN                                              {you missed a required }
  3557.                                                  { parameter}
  3558.         MyGotRequiredParams := errAEParamMissed
  3559.     ELSE                                              {the call to }    
  3560.                                                  { AEGetAttributePtr failed}
  3561.         MyGotRequiredParams := myErr;
  3562. END;
  3563. The code in Listing 2-15 uses the AEGetAttributePtr function to get the keyMissedKeywordAttr attribute. This attribute contains the first required parameter, if any, that your handler didn’t retrieve. If AEGetAttributePtr returns the errAEDescNotFound result code, the Apple event doesn’t contain a keyMissedKeywordAttr attribute. If the Apple event doesn’t contain this attribute, then your handler has extracted all of the parameters that the client application considered required. 
  3564. If the AEGetAttributePtr function returns noErr as the result code, then the attribute does exist, meaning that your handler has not extracted all of the required parameters. In this case, your handler should return an error and not process the Apple event.
  3565. The first remaining required parameter is specified by the data of the keyMissedKeywordAttr attribute. If you want this data returned, specify a buffer to hold the data. Otherwise, specify NIL as the buffer and 0 as the size of the buffer. If you specify a buffer to hold the data, you can check the value of the actualSize parameter to see if the data is larger than the buffer you allocated.
  3566. For more information about specifying Apple event parameters as optional or required, see “Specifying Optional Parameters for an Apple Event” on page 2-112.
  3567. Replying to an Apple Event
  3568. Your handler routine for a particular Apple event is responsible for performing the action requested by the Apple event, and can optionally return data in a reply Apple event. The Apple Event Manager passes a default reply Apple event to your handler. The default reply Apple event has no parameters when it is passed to your handler. Your handler can add parameters to the reply Apple event. If the client application requested a reply, the Apple Event Manager returns the reply Apple event to the client. 
  3569. The reply Apple event is identified by the kCoreEventClass event class and by the kAEAnswer event ID. If the client application specified the kAENoReply flag in the reply parameter of the AESend function, the Apple Event Manager passes a null descriptor record (a descriptor record of type typeNull, which does not contain any data) to your handler instead of a default reply Apple event. Your handler should check the descriptor type of the reply Apple event before attempting to add any attributes or parameters to it. If your handler attempts to add an Apple event attribute or parameter to a null descriptor record, it will generate an error.
  3570. If the client application requests a reply, the Apple Event Manager prepares a reply Apple event for the client by passing a default reply Apple event to your handler. If the client application does not request a reply, the Apple Event Manager passes a null descriptor record (a descriptor record of type typeNull, which does not contain any data) to your handler instead of a default reply Apple event. The default reply Apple event has no parameters when it is passed to your handler. Your handler can add any parameters to the reply Apple event. If your application is a spelling checker, for example, you can return a list of misspelled words in a parameter. However, your handler should check the descriptor type of the reply Apple event before attempting to add any attributes or parameters to it. If your handler attempts to add an Apple event attribute or parameter to a null descriptor record, it will generate an error.
  3571. When your handler finishes processing an Apple event, it returns a result code to AEProcessAppleEvent. The AEProcessAppleEvent function returns this result code as its function result. If your handler returns a nonzero result code, and if you have not added your own keyErrorNumber parameter, the Apple Event Manager also returns this result code to the client application by putting the result code into a keyErrorNumber parameter for the reply Apple event. The client can check for the existence of this parameter to determine whether the handler performed the requested action.
  3572. The client application specifies whether it wants a reply Apple event or not by specifying flags (represented by constants) in the sendMode parameter of the AESend function.
  3573. If the client specifies the kAEWaitReply flag in the sendMode parameter, the AESend function does not return until the timeout specified by the timeoutInTicks parameter expires or the server applicatuon returns a reply. When the server application returns a reply, the reply parameter to AESend contains the reply Apple event that your handler returned to the AEProcessAppleEvent function. The client application must dispose of the reply event after it is finished with it; but the Apple Event Manager disposes of the reply event for the server application when the server’s handler returns to AEProcessAppleEvent.   
  3574. If the client specified the kAEQueueReply flag, the client receives the reply event at a later time during its normal processing of other events.
  3575. Your handler should always set its function result to noErr if it successfully handles the Apple event or to a nonzero result code if an error occurs. The Apple Event Manager automatically adds any nonzero result code that your handler returns to a keyErrorNumber parameter in the reply Apple event. In addition to returning a result code, your handler can also return an error string in the keyErrorString parameter of the reply Apple event. Your handler should provide meaningful text in the keyErrorString parameter, so that the client can display this string to the user if desired.  
  3576. Listing 2-16 shows how to add the keyErrorString parameter to the reply Apple event. See “Adding Parameters to an Apple Event” on page 2-111 for a description of the AEPutParamPtr function.
  3577. Adding the keyErrorString parameter to the reply Apple event
  3578. FUNCTION MyHandler (theAppleEvent: AppleEvent; reply: AppleEvent;
  3579.                           handlerRefcon: LongInt): OSErr; 
  3580. VAR
  3581.     myErr:                OSErr;
  3582.     errStr:                Str255;
  3583. BEGIN
  3584.     {if an error occurs when handling an Apple event, set the }
  3585.     { function result and error string accordingly}
  3586.     IF myErr <> noErr THEN
  3587.     BEGIN
  3588.     MyHandler := myErr;      {result code to be returned--the }
  3589.                                 { Apple Event Manager adds this result }
  3590.                                 { code to the reply Apple event as the }
  3591.                                 { keyErrorNumber parameter}
  3592.     IF (reply.dataHandle <> NIL AND (myErr = noErr) THEN
  3593.     {add error string parameter to the default reply}
  3594.     errStr := 'Why error occurred'; {strings should normally }
  3595.                                               { be stored in resources}
  3596.     myErr := AEPutParamPtr(reply, keyErrorString, typeChar, 
  3597.                       @errStr[1], length(errStr));
  3598.     Exit(MyHandler);
  3599.     END;
  3600. END;
  3601. If your handler needs to return data to the client, it can add parameters to the reply Apple event. Listing 2-17 shows how a handler for the Multiply event (an imaginary Apple event that asks the server to multiply two numbers) might return the results of the multiplication to the client.
  3602. Adding parameters to the reply Apple event
  3603. FUNCTION MyMultHandler (theAppleEvent: AppleEvent; 
  3604.                                 reply: AppleEvent; 
  3605.                                 handlerRefcon: LongInt): OSErr; 
  3606. VAR
  3607.     myErr:                          OSErr;
  3608.     number1,number2:                        LongInt;
  3609.     replyResult:                        LongInt;
  3610.     actualSize:                        Size;
  3611.     returnedType:                        DescType;
  3612. BEGIN
  3613.     {get the numbers to multiply from the parameters of the }
  3614.     { Apple event; put the numbers in the number1 and number2         
  3615.     { variables and then perform the requested multiplication }
  3616.     myErr := MyDoMultiply(theAppleEvent, number1, 
  3617.                              number2, replyResult);
  3618.  
  3619. {return result of the multiplication in the reply Apple event}
  3620.     IF (reply.dataHandle <> NIL AND (myErr = noErr) THEN
  3621.     BEGIN
  3622.         myErr := AEPutParamPtr(reply, keyDirectObject, 
  3623.                                         typeLongInteger, @replyResult, 
  3624.                                         SizeOf(replyResult));
  3625.         MyMultHandler := myErr;
  3626.     END;
  3627. {if an error occurs, set the function result and error string }
  3628. { accordingly, as shown in Listing 2-16}
  3629. END;
  3630. Disposing of Apple Event Data Structures
  3631. Whenever you use Apple Event Manager functions to create a descriptor record, descriptor list, or Apple event record, the Apple Event Manager allocates memory for these data structures. Likewise, when you extract a descriptor record by using Apple Event Manager functions, the Apple Event Manager creates a copy of the descriptor record for you to use.
  3632. Whenever you finish using a descriptor record or descriptor list that you have created or extracted from an Apple event, you must dispose of the descriptor record—and thereby deallocate the memory it uses—by calling the AEDisposeDesc function.
  3633. Also, when you finish using the Apple event specified in the AESend function and have finished with the reply Apple event, you should dispose of their descriptor records using the AEDisposeDesc function. You should dispose of them even if AESend returns a nonzero result code. 
  3634. Once you finish using them, you should dispose of any Apple event data structures created or returned by these functions:
  3635. AECoerceDesc        AEDuplicateDesc
  3636. AECoercePtr        AEGetAttributeDesc
  3637. AECreateAppleEvent        AEGetKeyDesc
  3638. AECreateDesc        AEGetNthDesc
  3639. AECreateList        AEGetParamDesc
  3640. If you set the disposeInputs parameter to FALSE for any of the following functions, you should dispose of any Apple event data structures that they create or return:
  3641. CreateCompDescriptor        CreateRangeDescriptor
  3642. CreateLogicalDescriptor        CreateObjSpecifier
  3643. Even if you add a descriptor record to an Apple event (for example, when you create a descriptor record by calling AECreateDesc and then put a copy of it into a parameter of an Apple event by calling AEPutParamDesc), you are still responsible for disposing of the original descriptor record.
  3644. The Apple Event Manager does take care of disposing of the Apple event data structures when your handler returns to AEProcessAppleEvent; in this case, the Apple Event Manager disposes of the Apple event and the reply Apple event. Note that your handler is still responsible for disposing of any Apple event data structures created when extracting data from the Apple event. The Apple event and reply Apple event that your handler receives are only copies of the originals. The client application is responsible for disposing of the original data structures.
  3645. Your application is also responsible for disposing of some of the tokens it creates in the process of resolving an object specifier record. For information about token disposal, see “Defining Tokens” on page 2-169.
  3646. Interacting With the User
  3647. When your application receives an Apple event, it may need to interact with the user. For example, your application may need to display a dialog box asking for additional information or confirmation from the user. You must use the AEInteractWithUser function to make sure your application is in the foreground before it actually interacts with the user. 
  3648. Both the client application and the server application specify their preferences for user interaction. The AEInteractWithUser function checks the user interaction preferences set by each application. If both the client and the server allow user interaction, AEInteractWithUser usually posts a notification request, and the Notification Manager brings the server to the foreground after the user responds to the notification request. 
  3649. The AEInteractWithUser function can also bring the server application directly to the foreground, but only if the client application is the active application on the same machine and has set two flags in the sendMode parameter of the AESend function: the kAEWaitReply flag, which indicates that it is waiting for a reply, and the kAECanSwitchLayer flag, which indicates that it wants the server application to come directly to the foreground rather than posting a notification request.
  3650. A client application specifies its preferences for how the server application should interact with the user by setting various flags in the sendMode parameter to AESend. The Apple Event Manager sets the corresponding flags in the keyInteractLevelAttr attribute of the Apple event.
  3651. The server application sets its preferences with the AESetInteractionAllowed function. This function lets your application specify whether it allows interaction with the user as a result of receiving an Apple event from itself; from itself and other processes on the local machine; or from itself, local processes, and processes from another computer on the network.
  3652. Your application calls the AEInteractWithUser function before interacting with the user. If AEInteractWithUser returns the noErr result code, then your application is currently in the front and your application is free to interact with the user. If AEInteractWithUser returns the errAENoUserInteraction result code, the conditions didn’t allow user interaction and your application should not interact with the user.
  3653. The rest of this section explains how to set user interactions for the client and server applications and the practical effect of these settings when a server application needs to interact with a user.
  3654. Setting the Client Application’s User Interaction Preferences
  3655. The client application sets its user interaction preferences by setting flags in the sendMode parameter to the AESend function. The Apple Event Manager automatically adds the specified flags to the keyInteractLevelAttr attribute of the Apple event. These flags are represented by the following constants:
  3656. Flag        Description
  3657. kAENeverInteract        The server application should never interact with the 
  3658.         user in response to this Apple event. If this flag is set, 
  3659.         AEInteractWithUser returns the 
  3660.         errAENoUserInteraction result code. This flag is 
  3661.         the default when an Apple event is sent to a remote 
  3662.         application.
  3663. kAECanInteract        The server application can interact with the user in 
  3664.         response to this Apple event—by convention, if the 
  3665.         user needs to supply information to the server. If this 
  3666.         flag is set and the server allows interaction, 
  3667.         AEInteractWithUser either brings the server 
  3668.         application to the foreground or posts a notification 
  3669.         request. This flag is the default when an Apple event is 
  3670.         sent to a local application.
  3671. kAEAlwaysInteract        The server application can interact with the user in 
  3672.         response to this Apple event—by convention, 
  3673.         whenever the server application normally asks a user 
  3674.         to confirm a decision or interact in any other way, 
  3675.         even if no additional information is needed from the 
  3676.         user. If this flag is set and the server allows 
  3677.         interaction, AEInteractWithUser either brings the 
  3678.         server application to the foreground or posts a          
  3679.         notification request. 
  3680. The interpretation of the kAECanInteract and kAEAlwaysInteract flags depends on the server application only, and is not enforced by the Apple Event Manager. A Print event that specifies a range of pages to print provides a good example of the way these flags should be interpreted by a server application. If the client application sets the kAECanInteract flag before sending the Print event, the server application should not interact with the user, because it doesn’t require any additional information from the user in order to respond to the event. If the client application sets the kAEAlwaysInteract flag, the server application should attempt interact with the user as it normally would if it were the foreground application: that is, by displaying the Print dialog box so the user can confirm the specified range of pages.
  3681. If the client application doesn’t specify any of the three user interaction flags, the Apple Event Manager sets either the kAENeverInteract or the kAECanInteract flag in the keyInteractLevelAttr attribute of the Apple event, depending on the location of the server application. If the server application is on a remote computer, the Apple Event Manager sets the kAENeverInteract flag as the default. If the server application is on the local computer, the Apple Event Manager sets the kAECanInteract flag as the default.
  3682. In addition to the three user interaction flags, the client application can set another flag in the sendMode parameter to AESend to request that the Apple Event Manager immediately bring the server application directly to the foreground instead of posting a notification request:
  3683. Flag        Description
  3684. kAECanSwitchLayer        If both the client and server allow interaction, and if 
  3685.         the client application is the active application on the 
  3686.         local machine and is waiting for a reply (that is, it 
  3687.         has set the kAEWaitReply flag), 
  3688.         AEInteractWithUser brings the server directly to 
  3689.         the foreground. Otherwise, AEInteractWithUser 
  3690.         uses the Notification Manager to request that the 
  3691.         user bring the server application to the foreground.
  3692. Note that while the kAECanSwitchLayer flag must be set in order for the Apple Event Manager to bring the server application directly to the foreground, setting it will not, by itself, guarantee that the Apple Event Manager will bypass the notification request if user interaction is permitted. Another flag, the kAEWaitReply flag, must also be set in the sendMode parameter. The kAEWaitReply flag is one of three flags in the sendMode parameter that you can use to specify how your application should wait for a reply. (For a description of these flags, see “Requesting Services Through Apple Events” on page 2-33.) If the client application is not waiting for a reply, the user may have continued with other work, and an application switch might therefore be unexpected and would violate the principle of user control as described in the Human Interface Guidelines.
  3693. When a server application calls AEInteractWithUser, the function first checks to see if the kAENeverInteract flag in the keyInteractLevelAttr attribute of the Apple event is set. (The Apple Event Manager sets this attribute according to the flags specified in the sendMode parameter of AESend.) If the kAENeverInteract flag is set, AEInteractWithUser immediately returns the errAENoUserInteraction result code. If the client specified kAECanInteract or kAEAlwaysInteract, AEInteractWithUser checks the server’s preferences for user interaction.
  3694. Setting the Server Application’s User Interaction Preferences
  3695. The server sets its user interaction preferences by using the AESetInteractionAllowed function. You use this function to tell the Apple Event Manager the processes for which your application is willing to interact with the user.
  3696. myErr := AESetInteractionAllowed(level);
  3697. The level parameter is of type AEInteractAllowed. 
  3698. TYPE        AEInteractAllowed = (kAEInteractWithSelf, 
  3699.                                     kAEInteractWithLocal, 
  3700.                                     kAEInteractWithAll);
  3701. You can specify one of these values for the interaction level:
  3702. Flag        Description
  3703. kAEInteractWithSelf        User interaction with your server application in 
  3704.         response to an Apple event may be allowed only 
  3705.         when the client application is your own application—
  3706.         that is, only when your application is sending the 
  3707.         Apple event to itself.
  3708. kAEInteractWithLocal        User interaction with your server application in 
  3709.         response to an Apple event may be allowed only if the 
  3710.         client application is on the same computer as your 
  3711.         application. This is the default if the server 
  3712.         application does not call the function
  3713.         AESetInteractionAllowed.
  3714. kAEInteractWithAll         User interaction with your server application in 
  3715.         response to an Apple event may be allowed for any 
  3716.         client application on any computer.
  3717. If the server application does not set the user interaction level, AEInteractWithUser uses kAEInteractWithLocal as the value.
  3718. If the application sends itself an Apple event (that is, the application is both the client and the server) without setting the kAENeverInteract flag, AEInteractWithUser always allows user interaction. If the client application is a process on the local machine, and the server set the interaction level to the kAEInteractWithLocal or kAEInteractWithAll flag, then AEInteractWithUser allows user interaction. If the client is a process on a remote computer on the network, AEInteractWithUser allows user interaction only if the server specified the kAEInteractWithAll flag for the interaction level. In all other cases, AEInteractWithUser does not allow user interaction.
  3719. Requesting User Interaction
  3720. If your server application needs to interact with the user for any reason, it must call the AEInteractWithUser function to make sure it is in the foreground before it actually interacts with the user. When AEInteractWithUser allows user interaction (based on the client’s and server’s preferences), AEInteractWithUser brings the server application to the foreground—either directly or after the user responds to a notification request—and then returns a noErr result code. 
  3721. The first parameter to the AEInteractWithUser function specifies how long your handler is willing to wait for a response from the user. For example, if the timeout value is 15 seconds and the Apple Event Manager posts a notification request, an icon begin to flash in the upper-right corner of the screen, but it will stop flashing if the user does does not respond within 15 seconds. The icon will be either the server application’s icon or, if the server application specified a notification record as one of the parameters to the AEInteractWIthUser function, the icon specified in the notification record. Note that the timeout value passed to the AEInteractWithUser function is separate from the timeout value passed to the AESend function, which specifies how long the client application is willing to wait for the reply or return receipt from the server application.
  3722. If AEInteractWithUser does not receive a response from the user within the specified timeout value, AEInteractWithUser returns the errAETimeout result code. 
  3723. You may want to give the user a method of setting the interaction level. For example, some users may not want to be interrupted while background processing of an Apple event occurs, or they may not want to respond to dialog boxes when your application is handling Apple events sent from another computer.
  3724. Listing 2-18 illustrates the use of the AEInteractWithUser function. You call this function before your application displays a dialog box or otherwise interacts with the user when processing an Apple event. You specify a timeout value, a pointer to a Notification Manager record, and the address of an idle function as parameters to AEInteractWithUser.
  3725. Using the AEInteractWithUser function
  3726. myErr := AEInteractWithUser (kAEDefaultTimeOut, NIL, 
  3727.                                       @MyIdleFunction);
  3728. IF myErr <> noErr THEN
  3729.     {the attempt to interact failed; do any error handling}
  3730.     DoError(myErr)
  3731. ELSE
  3732.     {interact with the user by displaying a dialog box }
  3733.     { or by interacting in any other way that is necessary}
  3734.     DisplayMyDialogBox;
  3735. You can set a timeout value, in ticks, in the first parameter to AEInteractWithUser. Use the kAEDefaultTimeout constant if you want the Apple Event Manager to use a default value for the timeout value. The Apple Event Manager uses a timeout value of about one minute if you specify this constant. You can also specify the kNoTimeOut constant if your application is willing to wait an indefinite amount of time for a response from the user. Usually you should provide a timeout value, so that your application can complete processing of the Apple event in a reasonable amount of time.
  3736. You can provide a pointer to a Notification Manager record in the second parameter, or you can specify NIL to use the default record provided by AEInteractWithUser. The AEInteractWithUser function only uses a Notification Manager record when user interaction is allowed and the kAECanSwitchLayer flag in the keyInteractLevelAttr attribute is not set.
  3737. The last parameter to AEInteractWithUser specifies an idle function provided by your application. Your idle function should handle any update events, null events, operating-system events, or activate events while your application is waiting to be brought to the front. See “Writing an Idle Function” on page 2-150 for more information. 
  3738. Figure 2-19 illustrates a situation in which a client application might request a service from a server application that requires the server application to interact with the user in order to perform the requested service. In this example, a forms application requests a service from a database application.
  3739. A document with a button that triggers a Get Data event
  3740. Figure 2-19 shows part of an electronic form used to enter information about an order received by telephone. If the customer has ordered from the company before, the user can quickly retrieve the customer’s address and telephone number by clicking the Retrieve Customer Info button. Clicking this button causes the forms application to send a Get Data event to a database application called GigaBase that is currently open on the same computer. The Get Data event sent by the the forms application, which is the client application for the ensuing transaction, asks GigaBase, which is the server application, to locate the customer’s name in a table of addresses and return the customer’s address. When the forms application receives the return Apple event, it can add the address data to the appropriate fields in the order form.
  3741. If GigaBase, as the server application, locates more than one entry for the specified customer name, it will need to interact with the user in order to determine which data to return in the reply Apple event. In order to interact with the user, the server application must be in the foreground, so that it can display a dialog box like the one shown in Figure 2-20.
  3742. A server application displaying a dialog box that requests information from the user
  3743. Handling user interaction with the kAEWaitReply flag set
  3744. Figure 2-21 and Figure 2-22 illustrate two ways of dealing with the situation illustrated in Figure 2-19 and Figure 2-20. Figure 2-21 shows the circumstances in which AEInteractWithUser will bring the server application directly to the front. The client application sets the kAECanInteract, kAECanSwitchLayer, and kAEWaitReply flags in the sendMode parameter of the AESend function when it sends the Get Data event shown in the figure. By setting these flags, the client application indicates that it expects the user to wait until the address appears in the appropriate fields of the electronic form before continuing with any other work. In this case, an automatic layer switch will not surprise the user and will avoid the additional user action required to respond to a notification request. 
  3745. The server application in Figure 2-21 uses AESetInteractAllowed to set its own interaction level to kAEInteractWithLocal. After calling AEResolve to located the requested data, the server application discovers that there are two addresses that match the name the user typed into the eletronic form. The server application then calls AEInteractWithUser with a timeout value of kAEDefaultTimeOut. AEInterActWithUser brings the server application directly to the foreground and returns a noErr result code. The server application then displays the dialog box shown in Figure 2-20. When the user selects the desired customer and clicks OK in the dialog box, the server application sends the return Apple event to the client application, which returns to the foreground automatically and displays the requested customer information in the appropriate fields.
  3746. Figure 2-22 illustrates almost the same Apple event as that shown in Figure 2-21. The only difference is that the client application has set the kAEQueueReply flag instead of the kAEWaitReply flag in the sendMode parameter of the Get Data event, and has not set the kAECanSwitchKLayer flag. This combination of flags indicates that the client application expects the user to continue filling in other parts of the form, such as the items being ordered; the address will just appear after a while, provided there is no duplicate name. In this case, an automatic layer switch would disrupt the user’s work. Instead of bringing the server application directly to the foreground, AEInterActWithUser uses the Notification Manager to post a notification request. After the user has reponded to the request and brought the server application to the front, AEInterActWithUser returns a noErr result code and the server application displays the dialog box shown in Figure 2-20. When the user selects the desired customer and clicks OK in the dialog box, the server application sends the return Apple event to the client application. In this case, the user must bring the client application back to the foreground manually.
  3747. Handling user interaction with the kAEQueueReply flag set  
  3748. Creating an Apple Event
  3749. You create an Apple event by using the AECreateAppleEvent function. You supply parameters that specify the event class and event ID, the target address, the return ID, and the transaction ID, and the AECreateAppleEvent function creates and returns an Apple event with the attributes set as your application requested. You should not directly manipulate the contents of the Apple event; rather, use Apple Event Manager functions to add additional attributes or parameters to it.
  3750. This example creates an imaginary Multiply event using the AECreateAppleEvent function. You specify the event class, the event ID, the address of the server application, a return ID, a transaction ID, and a buffer to store the returned Apple event as parameters to AECreateAppleEvent. 
  3751. myErr := AECreateAppleEvent(kArithmeticClass, kMultEventID,
  3752.                                       targetAddress, kAutoGenerateReturnID,
  3753.                                      kAnyTransactionID, theAppleEvent);
  3754. The event class here is identified by the kArithmeticClass constant and specifies that this event belongs to a specific class of Apple events for arithmetic operations. The event ID specifies the particular Apple event within the class—in this case, an Apple event that performs multiplication.
  3755. You specify the target of the Apple event in the third parameter to AECreateAppleEvent. The target address can identify an application on the local computer or another computer on the network. You can specify the address using a target ID record or session reference number. For processes on the local computer, you can also use a process serial number or application signature to specify the address. See “Specifying a Target Address” on page 2-116 for more information. 
  3756. You specify the return ID of the Apple event in the fourth parameter. The return ID provides a way to associate this Apple event with the server’s reply. The AECreateAppleEvent function assigns the specified return ID value to the keyReturnIDAttr attribute of the Apple event. If a server returns a standard reply Apple event (that is, an event of event class \qaevt\q and event ID \qansr\q) in response to this event, the Apple Event Manager will assign the reply event the same return ID. When you receive a reply Apple event, you can check the keyReturnIDAttr attribute to determine which outstanding Apple event the reply is responding to. You can use the kAutoGenerateReturnID constant to request that the Apple Event Manager generate a return ID that is unique to this session for the Apple event. Otherwise, you are responsible for making it unique. 
  3757. The fifth parameter specifies the transaction ID attribute of the Apple event. A transaction is a sequence of Apple events that are sent back and forth between the client and server applications, beginning with the client’s initial request for a service. All Apple events that are part of one transaction must have the same transaction ID.
  3758. You can use a transaction ID to indicate that an Apple event is one of a sequence of Apple events related to a single transaction. The kAnyTransactionID constant indicates that the Apple event is not part of a transaction.
  3759. The AECreateAppleEvent function creates an Apple event with only the specified attributes and no parameters. To add parameters or additional attributes, you can use other Apple Event Manager functions.
  3760. Adding Parameters to an Apple Event
  3761. You can use the AEPutParamPtr or AEPutParamDesc function to add parameters to an Apple event. When you use either of these functions, the Apple Event Manager adds the specified parameter to the Apple event. 
  3762. Use the AEPutParamPtr function when you want to add data specified in a buffer as the parameter of an Apple event. You specify the Apple event, the keyword of the parameter to add, the descriptor type, a buffer that contains the data, and the size of this buffer as parameters to the AEPutParamPtr function. The AEPutParamPtr function adds the data to the Apple event as a parameter with the specified keyword.
  3763. For example, this code adds a parameter to the Multiply event using the AEPutParamPtr function.
  3764. CONST        keyOperand1 = 'OPN1';
  3765. VAR
  3766.     number1:                        LongInt;
  3767.     theAppleEvent:                        AppleEvent;
  3768.     myErr:                        OSErr;
  3769.  
  3770. number1 := 10;
  3771. myErr := AEPutParamPtr(theAppleEvent, keyOperand1, 
  3772.                               typeLongInteger, @number1,
  3773.                               SizeOf(number1));
  3774. In this example, the Apple Event Manager adds the parameter containing the first number to the specified Apple event.
  3775. Use the AEPutParamDesc function to add a descriptor record to an Apple event. The descriptor record you specify must already exist. To create or get a descriptor record, you can use the AECreateDesc, AEDuplicateDesc, and other Apple Event Manager functions that return a descriptor record.
  3776. You specify the descriptor type, a buffer that contains the data, and the size of this buffer as parameters to the AECreateDesc function. The AECreateDesc function returns the descriptor record that describes the data.
  3777. This example creates a descriptor record for the second parameter of the Multiply event:
  3778. VAR
  3779.     number2:                         LongInt;
  3780.     multParam2Desc:                        AEDesc;
  3781.     myErr:                        OSErr;
  3782.  
  3783. number2 := 8;
  3784. myErr := AECreateDesc(typeLongInteger, @number2, SizeOf(number2),
  3785.                               multParam2Desc);
  3786. In this example, the AECreateDesc function creates a descriptor record with the typeLongInteger descriptor type and the data identified in the number2 variable.
  3787. Once you have created a descriptor record, you can use AEPutParamDesc to add the data to an Apple event parameter. You specify the Apple event to add the parameter to, the keyword of the parameter, and the descriptor record of the parameter as parameters to the AEPutParamDesc function.
  3788. This example adds a second parameter to the Multiply event using the AEPutParamDesc function.
  3789. CONST        keyOperand2 = 'OPN2';
  3790.  
  3791. myErr := AEPutParamDesc(theAppleEvent, keyOperand2, 
  3792.             multParam2Desc);
  3793. This example adds the keyOperand2 keyword and the descriptor record created in the previous example as the second parameter to the specified Apple event. 
  3794. You can also create a descriptor record without using Apple Event Manager routines. For example, this example generates an alias descriptor record from an existing alias handle:
  3795. WITH myAliasDescDo
  3796.    BEGIN
  3797.    descriptorType := typeAlias;
  3798.    dataHandle := myAliasHandle;
  3799.    END;
  3800. Whatever method you use to create a descriptor record, you can add it to an Apple event parameter by using AEPutParamDesc.
  3801. After adding parameters to an Apple event, you can send the Apple event using the AESend function. See “Sending an Apple Event” on page 2-143 for information on using this function.
  3802. Specifying Optional Parameters for an Apple Event
  3803. The parameters for a given Apple event are listed in the Apple Event Registry: Standard Suites as either required parameters or optional parameters. When sending an Apple event, your application should include all of the parameters that are listed as required. Your application does not normally have to include Apple event parameters that are listed as optional; the target application uses default values for optional parameters if your application does not provide them. The Apple Event Registry: Standard Suites defines the default value a target application should use for each optional parameter of a specific Apple event.
  3804. For example, the definition of the Create Publisher event includes an optional parameter that specifies the Apple event object to publish. If this parameter is omitted, the target application creates a publisher for the current selection. The definition of the Create Publisher event also includes an optional parameter that specifies the location of the edition container to create. If this parameter is omitted, the target application uses the location specified in the application’s default edition container. 
  3805. Your application adds optional parameters to an Apple event the same way it adds required parameters, using the AECreateDesc, AEPutParamPtr, and AEPutParamDesc functions as described in the previous section, “Adding Parameters to an Apple Event.” The Apple Event Manager does not automatically keep track of which parameters are optional and which are required. Instead, the source application indicates which Apple event parameters it considers optional by listing the keywords for those parameters in the keyOptionalKeywordAttr attribute.
  3806. The keyOptionalKeywordAttr attribute does not contain the optional parameters; it simply lists the keywords of any parameters for the Apple event that the source application wants to identify as optional. Although the source application is responsible for providing this information in the keyOptionalKeywordAttr attribute of an Apple event, it is not required to provide this attribute.
  3807. If a keyword for an Apple event parameter is not included in the keyOptionalKeywordAttr attribute, the source application expects the target application to accept the Apple event parameter identified by that keyword. If a target application cannot accept the parameter, it should return the result code errAEEventNotHandled. If a target application cannot accept a parameter whose keyword is listed in the keyOptionalKeywordAttr attribute, it should ignore that parameter and attempt to handle the Apple event as it normally does.
  3808. A source application can choose not to list the keyword for an Apple event parameter in the keyOptionalKeywordAttr attribute even if that parameter is listed in the Apple Event Registry: Standard Suites as an optional parameter. This has the effect of forcing the target application to treat the parameter as required for a particular Apple event. If the target application supports the parameter, it should handle the Apple event as the client application expects. If the target application does not support the parameter and calls an application-defined routine such as MyGotRequiredParams to check whether it has received all the required parameters, it finds that there’s another parameter that the client application considered required, and should return the result code errAEEventNotHandled. 
  3809. If a source application wants a target application to attempt to handle an Apple event regardless of whether the target application supports a particular Apple event parameter included in that Apple event, the source application should list the keyword for that parameter in the keyOptionalKeywordAttr attribute. 
  3810. It is up to the source application to decide whether to list a parameter that is described as optional in the Apple Event Registry: Standard Suites in the keyOptionalKeywordAttr attribute of an Apple event. For example, if the definition of the Print Documents event were extended to include an optional keyPageRange parameter that specifies a page range, the source application might decide whether or not to list the keyword keyPageRange in the keyOptionalKeywordAttr attribute according to the characteristics of the print request. If the source application were attempting to print only three pages of a 500-page document, it could choose not to add the keyword keyPageRange to the keyOptionalKeywordAttr attribute; in this case, only target applications that supported the keyPageRange parameter would attempt to handle the event. If the source application were attempting to print one page of a one-page document, it could choose to add the keyword keyPageRange to the keyOptionalKeywordAttr attribute; in this case, it would get the same result regardless of whether the target application supported the keyPageRange parameter.
  3811. If your application chooses to provide the keyOptionalKeywordAttr attribute for an Apple event, it should first create a descriptor list that specifies the keywords of the optional parameters, then add it to the Apple event as a keyOptionalKeywordAttr attribute. 
  3812. Listing 2-19 shows an application-defined routine, MyCreateOptionalKeyword, that creates the keyOptionalKeywordAttr attribute for the Create Publisher event.
  3813. Creating the optional keyword for the Create Publisher event
  3814. FUNCTION MyCreateOptionalKeyword(createPubAppleEvent: AppleEvent) 
  3815.                                             : OSErr;
  3816. VAR
  3817.     optionalList:                    AEDescList;
  3818.     myErr:                    OSErr;
  3819. BEGIN                                
  3820.     {create an empty descriptor list}
  3821.     myErr := AECreateList(NIL, O, FALSE, @optionalList);
  3822.     {add the keywords for the optional parameters to the list}
  3823.     myErr := AEPutPtr(&optionalList, 1, 'keyw', 
  3824.                             keyDirectObject, sizeOf(keyDirectObject));
  3825.     myErr := AEPutPtr(&optionalList, 2, 'keyw', 
  3826.                             keyAEEditionFileLoc, 
  3827.                             sizeOf(keyAEEditionFileLoc));
  3828.     {create the keyOptionalKeywordAttr attribute and add it }
  3829.     { to the Create Publisher event}
  3830.     myErr := AEPutAttributeDesc(createPubAppleEvent,
  3831.                                          keyOptionalKeywordAttr, 
  3832.                                         @optionalList);
  3833.     MyCreateOptionalKeyword := myErr;
  3834.     {add your own error checking}
  3835. END;
  3836. The MyCreateOptionalKeyword function shown in Listing 2-19 adds the keyword of each parameter that the source application considers optional to a descriptor list as a descriptor record with the descriptor type 'keyw' and data that consists of a keyword. The function specifies that the target application does not need to support parameters identified by the keywords keyDirectObject and keyAEEditionFileLoc in order to handle the Create Publisher event. (These are the parameters that specify the Apple event object to publish and the location of the edition container.) After adding these keywords to the descriptor list, the function creates the keyOptionalKeywordAttr attribute using the AEPutAttributeDesc function.
  3837. Typically a target application does not examine the keyOptionalKeywordAttr attribute directly. Instead, a target application that supports a parameter that’s listed in the Apple Event Registry: Standard Suites as optional attempts to extract the parameter from the Apple event (using AEGetParamDesc, for example); if it can’t extract the parameter, it uses the default value, if any, listed in the Apple Event Registry. A target application can use the keyMissedKeywordAttr attribute to return the first required parameter (that is, considered required by the source application), if any, that it did not retrieve from the Apple event. The keyMissedKeywordAttr attribute does not return any parameters whose keywords are listed in the keyOptionalKeywordAttr attribute of the Apple event.       
  3838. Specifying a Target Address
  3839. When you create an Apple event, you must specify the address of the target. The target address identifies the particular application or process to which you want to send the Apple event. You can send Apple events to applications on the local machine or on remote computers on the network. 
  3840. These are the descriptor types that identify the four methods of addressing an Apple event.
  3841. typeApplSignature        The application signature of the target
  3842. typeSessionID        The session reference number of the target
  3843. typeTargetID        The target ID record of the target
  3844. typeProcessSerialNumber        The process serial number of the target
  3845. To address an Apple event to a target on a remote computer on the network, you must use either the typeSessionID or typeTargetID descriptor type.  
  3846. If your application sends an Apple event to itself, it should address the Apple event using a process serial number. Use the kCurrentProcess constant to specify the process serial number of your application. This is the fastest way for your application to send an Apple event to itself.
  3847. You can use any of the four address types when sending an Apple event to another application on the local computer. The chapter “The Event Manager” in Inside Macintosh: Macintosh Toolbox describes all four types of addresses. 
  3848. To allow the user to choose the target of an Apple event, use the PPCBrowser function. The PPCBrowser function presents a standard user interface for choosing a target application, much as the Standard File Package provides a standard user interface for opening and saving files. The PPCBrowser function returns information about the application the user chose in a target ID record. (Listing 2-21 on page 2-118 shows how to use the PPCBrowser function to let the user choose a target.) 
  3849. You specify the address using an address descriptor record (a descriptor record of data type AEAddressDesc). You must create a descriptor record of this type and then add it to the Apple event using the AECreateAppleEvent function.
  3850. You can use the AECreateDesc function to create address descriptor records for any of the four types of target addresses. Listing 2-20 shows four possible ways to create an address, each using a different address type.
  3851. Creating a target address
  3852. PROCEDURE SetTargetAddresses(VAR targetAddress1, targetAddress2,
  3853.                                       targetAddress3, targetAddress4: 
  3854.                                       AEAddressDesc; toTargetID: TargetID; 
  3855.                                       thePSN: ProcessSerialNumber; 
  3856.                                       theSignature: OSType; 
  3857.                                       theSessionRef: PPCSessRefNum);
  3858. VAR
  3859.     myErr:             OSErr;
  3860.  
  3861. BEGIN
  3862.     myErr := AECreateDesc(typeTargetID, @toTargetID,
  3863.                                  SizeOf(toTargetID), targetAddress1);
  3864.     myErr := AECreateDesc(typeProcessSerialNumber, @thePSN, 
  3865.                                  SizeOf(thePSN), targetAddress2);
  3866.     myErr := AECreateDesc(typeApplSignature, @theSignature, 
  3867.                                  SizeOf(theSignature), targetAddress3);
  3868.     myErr := AECreateDesc(typeSessionID, @theSessionRef, 
  3869.                                  SizeOf(theSessionRef), targetAddress4);
  3870.     {add your own error checking}
  3871. END;
  3872. You specify the descriptor type for the address, a pointer to the buffer containing the address, and the size of the buffer to the AECreateDesc function to create an address descriptor record. The AECreateDesc function returns an address descriptor record with the specified characteristics.
  3873. After creating an address, you can specify the address in the AECreateAppleEvent function. See “Creating an Apple Event” on page 2-110 for an example using the AECreateAppleEvent function. 
  3874. When you specify an address to the AECreateAppleEvent function, the Apple Event Manager stores the address in the keyAddressAttr attribute of the Apple event. 
  3875. If you use the PPCBrowser function to allow the user to choose an Apple event’s target, your application must create a target ID record based on the user’s choice. Listing 2-21 shows how to create a target ID record using the information returned from the PPCBrowser function and create an address descriptor record using the AECreateDesc function.
  3876. Specifying a target address in an Apple event by using the PPCBrowser function
  3877. FUNCTION GetTargetAddress (myPrompt: Str255; myAppStr: Str255;
  3878.                                     VAR myPortInfo: PortInfoRec; 
  3879.                                     VAR targetAddress: AEAddressDesc; 
  3880.                                     VAR toTargetID: targetID): OSErr;
  3881.  
  3882. VAR
  3883.     myErr: OSErr;
  3884. BEGIN                        {use PPCBrowser to let user choose the target}
  3885.     myErr := PPCBrowser(myPrompt, myAppStr, FALSE, 
  3886.                               toTargetID.location, myPortInfo, NIL, '');
  3887.     IF myErr <> noErr THEN
  3888.         DoError(myErr)
  3889.     ELSE 
  3890.     BEGIN
  3891.     toTargetID.name := myPortInfo.name;
  3892.                {create the descriptor record for the target address}
  3893.     myErr := AECreateDesc(typeTargetID, @toTargetID, 
  3894.                                  SizeOf(toTargetID), targetAddress);
  3895.     IF myErr <> noErr THEN
  3896.         DoError(myErr);
  3897.     END;
  3898.     GetTargetAddress := myErr;
  3899.     {add your own error checking}
  3900. END;
  3901. See the chapter “The Program-to-Program Communications Toolbox” in this book for more information on using the PPCBrowser function.
  3902. Creating an Object Specifier Record
  3903. If your application requests a service that requires the target application to locate an Apple event object, your application must include an object specifier record describing the Apple event object as a parameter of the Apple event used to request the service. This section describes how to use the four keyword-specified descriptor records introduced in “Working With Object Specifier Records,” which begins on page 2-38, to specify the class ID, container, key form, and key data for an object specifier record. You need to read this section only if your application supports the Core suite or any of the functional-area suites in the Apple Event Registry: Standard Suites. 
  3904. Your application does not need to create object specifier records in order to respond to the standard Apple events or to be scriptable—that is, capable of responding to scripts written in a scripting language. However, you need to know how object specifier records are constructed in order to write object accessor functions for your application. For an overview of the way the Apple Event Manager works with object accessor functions to resolve object specifier records, see “Resolving Object Specifier Records,” which begins on page 2-53.
  3905. Since the internal structure of an object specifier record is nearly identical to the internal structure of an AE record, it is possible to use AECreateList, AEPutPtr, and AEPutKeyDesc to add the four keyword-specified descriptor records to an AE record, then use AECoerceDesc to coerce the AE record to a descriptor record of type typeObjectSpecifier. However, it is usually preferable to use the CreateObjSpecifier function to accomplish the same goal. The CreateObjSpecifier function adds the keyword-specified descriptor records directly to an object specifier record, thus eliminating several steps that are required if you create an AE record first. The instructions that follow make use of CreateObjSpecifier. 
  3906. To specify the class ID for an object specifier record, your application must create a keyword-specified descriptor record with the keyword keyAEDesiredClass that contains the appropriate object class ID. You can specify the object class ID as the first parameter to the CreateObjSpecifier function, which uses it to create a keyword-specified descriptor record with the keyword keyAEDesiredClass as part of an object specifier record. 
  3907. To specify the container for an object specifier record, your application must create a keyword-specified descriptor record with the keyword keyAEContainer that fully describes the container of the Apple event object. Since the container for an Apple event object is usually another Apple event object, the container is usually specified by another object specifier record. The ability to nest one object specifier record within another in this way makes it possible to identify a chain of containers that fully describes the location of one or more Apple event objects. 
  3908. To specify the complete container hierarchy of an Apple event object, your application must create a series of nested object specifier records, starting with the object specifier record for the Apple event object whose container is the outermost container. With the exception of this first object specifier record, each object specifier record specifies another object specifier record in the chain as a container. For example, Figure 2-23 shows a series of nesting object specifier records that specify the first row of a table named “Summary of Sales, 1991” in a document named “Sales Report.” The container specified for the object specifier record on the right side of the figure describes the outermost container in the container hierarchy—the container for the document “Sales Report.”  
  3909. Nesting object specifier records that specify a container hierarchy
  3910. Since a container must be specified for each Apple event object in a container hierarchy, a special descriptor record called the null descriptor record is always used to represent the outermost container. A null descriptor record is a descriptor record whose descriptor type is typeNull and whose data is a NIL handle. A null descriptor record used in a keyword-specified descriptor record with the keyword keyAEContainer specifies an application’s default container, the outermost container for any container hierarchy in that application.  
  3911. In Figure 2-23, the object specifier record for the document on the right side of the figure uses a null descriptor record to specify the document’s container—that is, the default container for the SurfWriter application. The object specifier record for the document identifies it as the document with the name “Sales Report”; the object specifier record for the table identifies it as the table named “Summary of Sales, 1991” in the document “Sales Report”; and the object specifier record for the row identifies it as the first row of the table named “Summary of Sales, 1991” in the document “Sales Report.”
  3912. To specify the default container for an object specifier record, you can use AECreateDesc to create a null descriptor record, which you can then pass as the second parameter to the CreateObjSpecifier function. CreateObjSpecifier uses this descriptor record to create a keyword-specified descriptor record with the keyword keyAEContainer as part of an object specifier record. 
  3913. The object specifier record that specifies the default container is always the first record you create in a series of nested object specifier records that specifies the complete container hierarchy for an Apple event object. Each of the other object specifier records in the chain (moving from right to left in Figure 2-23) uses the previously created object specifier record to specify its container. As with the null descriptor record, you can pass an object specifier record as the second parameter to the CreateObjSpecifier function, which uses it to create a keyword-specified descriptor record with the keyword keyAEContainer.
  3914. In addition to descriptor records of typeNull and typeObjectSpecifier, you can use descriptor records of type typeObjectBeingExamined and type typeCurrentContainer to specify an Apple event object’s container. For more information about these descriptor types, which are used to specify tests and ranges, respectively, see “Creating a Complex Object Specifier Record” on page 2-128.<36pt\>\x12 <8bat\>u
  3915. To specify the key form for an object specifier record, your application must create a keyword-specified descriptor record with the keyword keyAEKeyForm that contains a constant describing the form of the key data. For example, the object specifier records in Figure 2-23 that specify the document and the table each have a key form of formName, which means that the key data identifies the document and the table by their names, “Sales Report” and “Summary of Sales, 1991,” respectively. Similarly, the object specifier record in Figure 2-23 that specifies the first row in the table has a key form of formAbsolutePosition, which means that the key data identifies the position of the row compared to other rows in the same container. 
  3916. You can specify a key form constant as the third parameter to the CreateObjSpecifier function, which uses the specified key form to create a keyword-specified descriptor record with the keyword keyAEKeyForm as part of an object specifier record. 
  3917. Your application can support either simple or complex object specifier records. A simple object specifier record can specify one element in a container by absolute position, by name, or as a property of the container. A complex object specifier record can specify one element using any of the methods available to a simple object specifier record, and can also specify complex tests, ranges, and relative positions to identify groups of related elements.
  3918. Simple object specifier records can specify one of the following key forms:
  3919. Key form        Corresponding key data
  3920. formPropertyID         The property ID for an element’s property; for example, pStyle or pFont
  3921. formName        The value of an element’s name; for example, "MyDoc"    
  3922. formAbsolutePosition        The position of an element in relation to the beginning or end of its container; for example, the fifth word in a paragraph
  3923. If you need to specify Apple event objects in a more sophisticated manner, you must use a complex object specifier record, which can specify one of the following key forms:
  3924. Key form        Corresponding key data
  3925. formPropertyID         Specifies the property ID for an element’s property; for example, pStyle or pFont.
  3926. formName        Specifies the value of an element’s name; for example, "Sales Report"    .
  3927. formAbsolutePosition        Specifies the position of one or more elements in relation to the beginning or end of their container; for example, the fifth word in a paragraph, or all the words in a paragraph.
  3928. formRelativePosition        Specifies an element immediately before or after another element; for example, the word after the third paragraph.
  3929. formTest        Specifies one or more elements that pass a test. Values of one or more properties or elements can be tested; for example, the first paragraph that is centered and begins with the word “Wild.”
  3930. formRange        Specifies a list of elements between two other elements; for example, the words between “Green” and “Blue,” inclusive. 
  3931. To specify the key data for an object specifier record, your application must create a keyword-specified descriptor record with the keyword keyAEKeyData that contains the appropriate data for the specified key form. For simple object specifier records, the key data consists of the name of property, the name of an Apple event object, or a number indicating absolute position, which require descriptor records of type typeType, typeText, or typeLongInteger, respectively. You can use AECreateDesc to create the descriptor record, which you can then specify as the fourth parameter for the CreateObjSpecifier function. CreateObjSpecifier uses this descriptor record to create a keyword-specified descriptor record with the keyword keyAEKeyData as part of an object specifier record. 
  3932. For complex object specifier records, the key data usually consists of several interconnected descriptor records that collectively define a relative position, a test, or a range. For information about specifying the key data for a complex object specifier record, see “Creating a Complex Object Specifier Record” on page 2-128.
  3933. A simple object specifier record requires less work to support than a complex object specifier record, but permits the specification of a more limited range of Apple event objects. Although complex object specifier records can be difficult to construct, they allow your application great flexibility in specifying Apple event objects. 
  3934. Simple object specifier records can be used with all the Apple events in the Core suite and a few others. Applications that support complex object specifier records also support simple object specifier records. If your application supports only simple object specifier records and it receives a complex object specifier record, it should return the result code errAEeventNotHandled.
  3935. The key forms available for use in a complex object specifier record are not limited to those listed in this section. The key form formWhose, which is described in “Supporting Whose Descriptor Records” on page 2-170, is a special key form created by the Apple Event Manager that optimizes the resolution of complex object specifier records for applications that support whose descriptor records. You can also define your own key forms for use by your own application; if you think you need to do this, check with AEDA first. 
  3936. For information about using object accessor functions with the AEResolve function to resolve simple object specifier records, see “Resolving Object Specifier Records,” which begins on page 2-53.
  3937. Creating a Simple Object Specifier Record
  3938. This section shows how to use the CreateObjSpecifier function to create a simple object specifier record. You can also create each descriptor record for a simple object specifier record separately, then combine them in an AE record and coerce the AE record to an object specifier record. However, in most cases it’s preferable to use the CreateObjSpecifier function, which eliminates several steps that are required if you create an AE record first. 
  3939. As explained in the previous section, you can specify constants (which represent descriptor types, or four-letter codes) for the desired class and key form, and descriptor records for the container and key data, as parameters to the CreateObjSpecifier function. The CreateObjSpecifier function automatically creates the necessary keyword-specified descriptor records for the class ID, container, key form, and key data, and returns the resulting object specifier record as a descriptor record of type typeObjectSpecifier.
  3940. Listing 2-22 shows how the CreateObjSpecifier function creates an object specifier record from parameters that an application specifies.
  3941. Creating an object specifier record using CreateObjSpecifier
  3942. VAR
  3943.     desiredClass:                             DescType; 
  3944.     myObjectContainer:                             AEDesc; 
  3945.     myKeyForm:                             DescType; 
  3946.     myKeyDataDesc:                             AEDesc; 
  3947.     disposeInputs:                             Boolean; 
  3948.     myObjSpecRec:                             AEDesc
  3949.     myErr:                            OSErr;
  3950.  
  3951. desiredClass := cRow;
  3952. myObjectContainer := MygetContainer;
  3953. myKeyForm := formAbsolutePosition;
  3954. myKeyDataDesc := MyGetKeyData;
  3955. {create an object specifier record}
  3956.     myErr := CreateObjSpecifier(desiredClass, myObjectContainer, 
  3957.                                             myKeyForm, myKeyDataDesc, 
  3958.                                             TRUE, myObjSpecRec);
  3959.  
  3960. The code shown in Listing 2-22 demonstrates how an application might use the CreateObjSpecifier function to create four keyword-specified descriptor records as part of a descriptor record of typeObjectSpecifier. The CreateObjSpecifier function returns a result code of noErr if the object specifier record was successfully created. The object specifier record returned in the myObjSpecRec parameter describes an Apple event object of the class specified by the desiredClass parameter, located in the container specified by the myObjectContainer parameter, with the key form specified by the myKeyForm parameter and key data specified by the myKeyDataDesc parameter. You can specify TRUE in the disposeInputs parameter if you want the CreateObjSpecifier function to dispose of the descriptor records you created for the myObjectContainer and myKeyData parameters. If you specify FALSE, then your application is responsible for disposing of these leftover descriptor records. 
  3961. Listing 2-23 shows an application-defined function that uses CreateObjSpecifier to create an object specifier record for the first row in the table named “Summary of Sales” in the document “Sales Report,” then uses the object specifier record returned in the myObjSpecRec parameter as the direct parameter for a Get Data event. 
  3962. Using CreateObjSpecifier in an application-defined function
  3963. FUNCTION MyRequestRowFromTarget (targetAddress: AEAddressDesc; 
  3964.                                              reply: AppleEvent): OSErr;
  3965. VAR
  3966.     desiredClass:                                 DescType;
  3967.     myKeyForm:                                DescType;
  3968.     myObjectContainer:                                AEDesc;
  3969.     myObjSpecRec:                                 AEDesc;
  3970.     myKeyDataDesc:                                AEDesc;
  3971.     keyData:                                LongInt;
  3972.     theAppleEvent:                                AppleEvent;
  3973.     myErr:                                OSErr;
  3974.  
  3975. BEGIN
  3976.     desiredClass := cRow;                                                {specify the class}
  3977.     {create the container for the row}
  3978.     myErr := MyCreateTableContainer(myObjectContainer, 
  3979.                                             \qSummary of Sales, 1991\q, \qSales Report\q);
  3980.     myKeyForm := formAbsolutePosition;                                                {specify the key form}
  3981.     keyData := 1;                    {specify the key data for the row}
  3982.     IF myErr = noErr THEN
  3983.     myErr := AECreateDesc(typeLongInteger,@keyData, sizeof(keyData), 
  3984.                                     myKeyDataDesc);
  3985.     {create the object specifier record}
  3986.     IF myErr = noErr THEN
  3987.     myErr := CreateObjSpecifier(desiredClass, myObjectContainer, myKeyForm, 
  3988.                                                 myKeyDataDesc, TRUE, myObjSpecRec);
  3989.     {myObjSpecRec now describes an Apple event object, and will become the} 
  3990.     { direct parameter of a Get Data event; first create the Get Data event}
  3991.     IF myErr = noErr THEN
  3992.         myErr := AECreateAppleEvent(kAECoreSuite, kAEGetData, targetAddress,
  3993.                                                 kAutoGenerateReturnID, 
  3994.                                                 kAnyTransactionID, theAppleEvent);
  3995.     {add myObjSpecRec as the direct parameter of the Get Data event}
  3996.     IF myErr = noErr THEN
  3997.         myErr := AEPutParamDesc(theAppleEvent, keyDirectObject, 
  3998.                                             myObjSpecRec);
  3999.     {now send the Get Data event}
  4000.     IF myErr = noErr THEN
  4001.         myErr := AESend(theAppleEvent, reply, kAEWaitReply + kAENeverInteract, 
  4002.                                 kAENormalPriority, 120, @myIdleFunction, NIL);
  4003.     MyRequestRowFromTarget := myErr;
  4004. END;
  4005. The MyRequestRowFromTarget function shown in Listing 2-23 specifies the class ID as cRow, indicating that the desired Apple event object is a row in a table. It uses the application-defined function MyCreateTableContainer to create an object specifier record for the table that constains the row, passing “Summary of Sales, 1991” and “Sales Report” as the second and third parameters to identify the name of the table and the name of the document that contains the table. (The next section, “Specifying the Container Hierarchy,” explains how to construct the MyCreateTableContainer function). It then specifies the key form as the constant formAbsolutePosition, which indicates that the key data specifies the position of the row within its container; sets the keyData variable to 1, indicating the first row, and uses AECreateDesc to create a descriptor record for the key data; and uses CreateObjSpecifier to create the object specifier record that describes the desired word.
  4006. The desired row is now fully described by the myObjSpecRec variable, which contains a descriptor record of type typeObjectSpecifier that contains the three nesting object specifier records shown in Figure 2-23 on page 2-120. After using AECreateAppleEvent to create a Get Data event, the MyRequestRowFromTarget function uses the AEPutParamDesc function to add the myObjSpecRec variable to the Get Data event as a direct parameter, then uses AESend to send the Get Data event.
  4007. Specifying the Container Hierarchy
  4008. Since the container for an object specifier record usually consists of a chain of other object specifier records that specify the container hierarchy, your application must create all the object specifier records in the chain, starting with the record for the outermost container (see Figure 2-23 on page 2-120). Listing 2-24 and Listing 2-25 demonstrate how to use the CreateObjSpecifier function to create the first two object specifier records in such a chain: the records for a document and a table. 
  4009. Specifying a document container
  4010. FUNCTION MyCreateDocContainer (VAR myDocContainer: AEDesc;
  4011.                                         docName: Str255): OSErr;
  4012. VAR
  4013.     myDocDescRec:                    AEDesc;
  4014.     nullDescRec:                     AEDesc;
  4015.     myErr:                    OSErr;
  4016. BEGIN    
  4017.     {create a descriptor record for the name of the document}
  4018.     myErr := AECreateDesc(typeChar, @docName[1], 
  4019.                                  Length(docName), myDocDescRec);
  4020.     {create a null descriptor record}
  4021.     IF myErr = noErr THEN
  4022.         myErr := AECreateDesc(typeNull, NIL, 0, nullDescRec);
  4023.     {create a container (an object specifier record) to specify }
  4024.     { the document object}
  4025.     IF myErr = noErr THEN
  4026.         myErr := CreateObjSpecifier(cDocument, nullDescRec, 
  4027.                                                 formName, myDocDescRec, TRUE, 
  4028.                                                 myDocContainer);
  4029.     MyCreateDocContainer := myErr;
  4030. END;
  4031. The function MyCreateDocContainer in Listing 2-24 creates an object specifier record that identifies a document by name. It starts by using the AECreateDesc function to create two descriptor records: one of type typeChar for the name of the document, and one of type typeNull for the null descriptor record that specifies the default container (since the document is not contained in any other Apple event object). These two descriptor records can then be used as parameters for the CreateObjSpecifier function, which returns an object specifier record (that is, a descriptor record of type typeObjectSpecifier) in the myDocContainer variable. The object specifier record specifies an Apple event object of the object class cDocument in the container specified by the nullDescRec variable with a key form of formName and the key data specified by the MyDocDescRec variable. This object specifier can be used by itself to specify a document, or it can be used to specify the container for another Apple event object.
  4032. Listing 2-25 shows an application-defined function, MyCreateTableContainer, that creates an object specifier record describing a table contained in a document. The MyCreateTableContainer function uses the MyCreateDocContainer function shown in Listing 2-24 to create the object specifier record that specifies its container.
  4033. Specifying a table container
  4034. FUNCTION MyCreateTableContainer(VAR myTableContainer: AEDesc;
  4035.                                             tableName: Str255;
  4036.                                             docName: Str255): OSErr;
  4037. VAR
  4038.     myDocDescRec:                            AEDesc;
  4039.     myTableDescRec:                            AEDesc;
  4040.     myErr:                            OSErr;
  4041. BEGIN
  4042.     {create a container for the document}
  4043.     myErr := MyCreateDocContainer(myDocDescRec, docName);
  4044.     {create the table container, }
  4045.     { first specify the descriptor record for the key data }
  4046.     IF myErr = noErr THEN
  4047.     myErr := AECreateDesc(typeChar, @tableName[1], 
  4048.                                      Length(tableName), myTableDescRec);        IF myErr = noErr THEN
  4049.         myErr := CreateObjSpecifier(cTable, myDocDescRec, 
  4050.                                                 formName, myTableDescRec, 
  4051.                                                 TRUE, myTableContainer);
  4052.     MyCreateTableContainer:= myErr;
  4053. END;
  4054. The function MyCreateTableContainer in Listing 2-25 starts by using the function MyCreateDocContainer from Listing 2-24 to create an object specifier record that identifies the table’s container—the document in which the table is located. Then it uses the AECreateDesc function to create a descriptor record for the key data—a name that, when combined with the key form formName, will identify the table in the document. The object specifier record for the document and the descriptor record specifying the table’s name are passed to the function CreateObjSpecifier. It returns an object specifier record in the myTableContainer parameter that specifies an Apple event object of the object class cTable in the container specified by the MyDocDescRec variable with a key form of formName and the key data specified by the myTableDescRec variable. This object specifier record can be used by itself to specify a table, or it can be used to specify the container for another Apple event object.
  4055. Listing 2-23 uses the MyCreateTableContainer function shown in Listing 2-25 to specify the container hierarchy illustrated in Figure 2-23 on page 2-120.   
  4056. Creating a Complex Object Specifier Record
  4057. If you want your application to specify relative positions, tests, and ranges that identify groups of related Apple event objects for a server application, your application must include routines that create complex object specifier records. Complex object specifier records can specify at least four key forms that are not available to simple object specifier records: formRelativePosition, formTest, formRange, and formWhose. These additional key forms provide considerably more flexibility than the key forms available for simple object specifier records. You can also define key forms of your own, if necessary, for use in complex object specifier records.
  4058. Like a simple object specifier record, a complex object specifier record consists of four keyword-specified descriptor records. You can create the first descriptor record, for the object class ID, the same way you would for a simple object specifier record. When you create the other three keyword-specified descriptor records, however, you can use several additional Apple Event Manager routines and descriptor types to specify any combination of Apple event objects.
  4059. Both simple and complex object specifier records almost always include nested object specifier records that specify the container hierarchy for the requested Apple event object. In a simple object specifier record, the relationship between an Apple event object and its container is always simple containment: it is located inside its container. You can use one of two descriptor types to describe the container for a simple object specifier record: typeObjectSpecifier, for other object specifier records, or typeNull, for the default descriptor record that indicates the top of the container hierarchy.
  4060. In a complex object specifier record, the specified container may not actually contain the requested Apple event object. Instead, the relationship between the container and the element it contains can be defined differently, depending on the key form. In addition to the simple containment relationship that a simple object specifier record can describe, the key forms available to a complex object specifier record can describe the following kinds of relationships between a container and the elements it contains:
  4061. Key form        Relationship of container to its elements
  4062. formRelativePosition        The container is a single Apple event object or a group of Apple event objects that contains one or more elements; the elements are located immediately before or immediately after the container. For example, you can specify the table named “Summary of Sales, 1991” as the container for whatever follows it.
  4063. formTest or formWhose        The container is a single Apple event object or a group of Apple event objects that contains one or more elements that pass a test specified by the key data. For example, you can specify a document named “Sales Report” as the container for all the tables in that document that begin with the word “Sales.”  
  4064. formRange        The container consists of an Apple event object that contains a range of elements between two other elements in the same container. For example, you can specify the document “Sales Report” as the container for the range of paragraphs between a table named “Summary of Sales, 1991” and a table named “Summary of Sales, 1992.” 
  4065. In addition to these relationships, new key forms—either new standard key forms or custom key forms defined for a particular class of objects—can specify other relationships between specified Apple event objects and their container.
  4066. Object specifier records that specify the key forms formTest or formRange require key data that consists of several interconnected descriptor records, including object specifier records that identify either a group of elements to be tested or the boundary elements that demarcate a range. Object specifier records provided as part of the key data can specify their containers using two special descriptor types: typeObjectBeingExamined, which specifies a container that changes as a group of elements are tested one at a time, and typeCurrentContainer, which specifies the container for a boundary element in a range. Boundary elements of a range are always located in the same container as the range itself. Both of these descriptor types require NIL as their data, since they act much like variables whose value is supplied by the Apple Event Manager according to other information provided in the container hierarchy. The descriptor types typeObjectBeingExamined and typeCurrentContainer can be used only for object specifier records that are part of key data.
  4067. Complex object specifier records can therefore make use of a total of four descriptor types to specify containers:
  4068. Descriptor type        Corresponding data
  4069. typeObjectSpecifier         Any other object specifier record.
  4070. typeNull        NIL. Specifies the default container that indicates the 
  4071.         top of the container hierarchy. 
  4072. typeObjectBeingExamined        NIL. Specifies the container for an object specifier record that changes as a group of elements are tested one at a time. This descriptor type acts much like a variable whose value matches the element currently being tested. It is used only for object specifier records that are part of the key data corresponding to a key form of formtest.
  4073. typeCurrentContainer        NIL. Specifies a container for an element that demarcates one boundary in a range. The container for a boundary element is always the same as the container for the entire range. This descriptor type is used only for object specifier records that are part of the key data corresponding to a key form of formRange.  
  4074. You can specify the formPropertyID, formName, and formAbsolutePosition key forms for a complex object specifier record the same way you specify them for a simple object specifier record. However, in addition to providing data of descriptor type typeLongInteger for the key data that corresponds to a key form of formAbsolutePosition, you can provide data of descriptor type typeAbsoluteOrdinal that consists of one of these constants:  
  4075. Constant        Meaning
  4076. kAEFirst        The first element in the specified container. 
  4077. kAEMiddle        The element in the middle of the specified container.
  4078. kAELast        The last element in the specified container. 
  4079. kAEAny        A single element chosen at random from the specified 
  4080.         container. 
  4081. kAEAll        All the elements in the specified container. 
  4082. The other key forms that you can use in a complex object specifier record require your application to specify the key data using several descriptor types that are not available for simple object specifier records. The remainder of this section describes how to use the key forms formRelativePosition, formTest, and formRange, and provides sample code that illustrates how to create an object specifier record using the key form formTest. For information about the key form formWhose, see “Supporting Whose Descriptor Records” on page 2-170.
  4083. Specifying a Relative Position
  4084. The key form formRelativePosition allows you to specify key data identifying an element or a set of elements that are immediately before or after the specified container. For example, if the container is a table, you could use a key form of formRelativePosition to specify the paragraph before or after the table. To specify the key data for a key form of formRelativePosition, your application must create a descriptor record of typeEnumeration that specifies one of these constants:
  4085. Constant        Description
  4086. kAENext        Specifies the Apple event object after the specified container. 
  4087. kAEPrevious        Specifies the Apple event object before the specified container. 
  4088. You can use AECreateDesc to create a descriptor record that specifies one of these constants, then use CreateObjectSpecifier to add it to an object specifier record as a keyword-specified descriptor record. 
  4089. Specifying a Test
  4090. The key form formTest allows you to specify key data that identifies one or more elements in the specified container that pass a test. To specify the key data for a key form of formTest, your application must construct several interconnected descriptor records that specify logical expressions and, if necessary, comparisons. For example, to specify “the first row in which the First Name column equals ‘John’ and the Last Name column equals ‘Chapman’ in the table MyAddresses of the database GigaBase,” your application must construct a logical expression that applies the logical operator AND to two separate comparisons for each row: a comparison of the “First Name” column to the word “John” and a comparison of the “Last Name” column to the word “Chapman.” The listings in the remainder of this section demonstrate how to create a complex object specifier record for this example. 
  4091. Since both the database and the table in this example are specified by name, it would be convenient to have an application-defined routine that creates an object specifier record that uses the key form formName. The MyCreateFormNameObjSpecifier function shown in Listing 2-26 can be used for this purpose.
  4092. Creating an object specifier record with the key form formName
  4093. FUNCTION MyCreateFormNameObjSpecifier(class: DescType; 
  4094.                                 VAR container: AEDesc; 
  4095.                                 keyDataName: str255; 
  4096.                                 VAR resultObjSpecRec: AEDesc): OSErr;
  4097. VAR
  4098.     keyDataDescRec: AEDesc;
  4099.     myErr: OSErr;
  4100. BEGIN
  4101.     myErr := AECreateDesc(typeChar, @keyDataName[1], 
  4102.                                      Length(keyDataName), keyDataDescRec);
  4103.     IF myErr = noErr THEN
  4104.     myErr := CreateObjSpecifier(class, container, formName,
  4105.                                             keyDataDescRec, TRUE,
  4106.                                             resultObjSpecRec);
  4107. END;
  4108. The MyCreateFormNameObjSpecRec function shown in Listing 2-26 returns an object specifier record in the resultObjSpecRec parameter that describes an Apple event object of the class specified by the class parameter, located in the container specified by the container parameter, with the key form formName and key data specified by the keyDataName parameter. This function is used in Listing 2-29 on page 2-140 to create object specifier records that use the key form formName for the database and the table. 
  4109. The next object specifier that needs to be created specifies “the rows in which the First Name column equals ‘John’ and the Last Name column equals ‘Chapman’.” To identify the rows that pass this test, the Apple Event Manager needs to evaluate a two comparisons (the comparison of each row of the First Name column to the word “John,” and the comparison of each row of and the Last Name column to the word “Chapman”).
  4110. The Apple Event Manager evaluates comparisons and logical expressions on the basis of information in comparison descriptor records and logical descriptor records. A comparison descriptor record is a descriptor record of type typeCompDescriptor that the Apple Event Manager uses to compare the specified elements in a container, one at a time, either to another Apple event object or to the data in a descriptor record. A comparison descriptor record is a coerced AE record that consists of three keyword-specified descriptor records with the following keywords: 
  4111. Keyword        Description
  4112. keyAECompOperator        A descriptor record of type typeType that specifies one of several possible comparison operators. 
  4113. keyAEObject1        An object specifier record that identifies the element that is currently being compared to the Apple event object or data specified by the descriptor record identified by the keyword keyAEObject2. 
  4114. keyAEObject2        Either an object specifier record or another descriptor record. 
  4115. You can specify one of these constants for the data in a descriptor record specified by the keyword keyAECompOperator:
  4116. Constant        Comparison operator
  4117. kAEGreaterThan        > 
  4118. kAEGreaterThanEquals        ≥ 
  4119. kAEEquals        = 
  4120. kAELessThan        < 
  4121. kAELessThanEquals        ≤ 
  4122. kAEBeginsWith        Begins with 
  4123. kAEEndsWith        Ends with 
  4124. kAEContains        Contains  
  4125. Your application is not required to support all the comparison operators that are available. Not all comparison operators make sense for all objects; for example, the “begins with” operator probably doesn’t make sense for Apple event objects of type cRectangle. It is up to you to decide which comparison operators are appropriate for your application to support, and how to interpret them. If necessary, you can define your own custom comparison operators; if you think you need to do this, check with AEDA first.
  4126. You can use the CreateCompDescriptor function to create a comparison descriptor record, or you can create an AE record and use AECoerceDesc to coerce it to a comparison descriptor record. Listing 2-27 shows an example of an application-defined routine that creates an object specifier record and a descriptor record of typeChar, then uses the CreateCompDescriptor function to add them to a comparison descriptor record. 
  4127. Creating a comparison descriptor record
  4128. FUNCTION MyCreateComparisonDescRec (VAR compDesc: AEDesc;
  4129.                                                 colName: str255; 
  4130.                                                 name: str255): OSErr;
  4131. VAR
  4132.     logicalContainer, colNameDesc, nameDesc:                                                         AEDesc;
  4133.     myObjectExaminedContainer:                                                         AEDesc;
  4134.     myErr:                                                        OSErr;
  4135. BEGIN
  4136.     {create the object spec record for keyAEObject1 }
  4137.     { first create container}
  4138.     myErr := AECreateDesc(typeObjectBeingExamined, NIL, 0,
  4139.                                     myObjectExaminedContainer);
  4140.     {create key data}
  4141.     myErr := AECreateDesc(typeChar, @colName[1],
  4142.                                     Length(colName), colNameDesc);
  4143.     {now create the object spec record}
  4144.     myErr := CreateObjSpecifier(cColumn,
  4145.                                             myObjectExaminedContainer, 
  4146.                                             formName, colNameDesc, TRUE,
  4147.                                             logicalContainer);
  4148.     {create the descriptor record for keyAEObject2);
  4149.     myErr := AECreateDesc(typeChar, @name[1], Length(name), 
  4150.                                     nameDesc);
  4151.     {create the first logical term (comp descriptor record)}
  4152.     myErr := CreateCompDescriptor(kAEEquals, logicalContainer,
  4153.                                             nameDesc, TRUE, compDesc);
  4154.     MyCreateComparisonDescRec := myErr;
  4155.     {add your own error checking}
  4156. END;
  4157. The MyCreateComparisonDescRec function takes two strings and uses them to create a comparison descriptor record. The string passed in the second parameter specifies the name of the column whose contents should be compared to the string passed in the third parameter. First, the MyCreateComparisonDescRec function uses AECreateDesc to create a descriptor record of typeObjectBeingExamined, which is returned in the variable myObjectExaminedContainer. The code that follows uses AECreateDesc to create a descriptor record of descriptor type typeChar, whose data consists of the string in the variable colName, and which is returned in the variable colNameDesc. The code then passes the variables myObjectExaminedContainer and colNameDesc to the CreateObjSpecifier function, which uses them to create an object specifier record, returned in the logicalContainer variable, that will become the keyword-specified descriptor record with the keyword keyAEObject1.
  4158. Next, the MyCreateComparisonDescRec function uses AECreateDesc and the name parameter to create the descriptor record for keyAEObject2, which AECreateDesc returns in the nameDesc variable. Finally, the code passes the constant kAEEquals, the variable logicalContainer, and the variable nameDesc to the CreateCompDescriptor function, which creates a comparison descriptor record that allows the Apple Event Manager (with the help of object comparison functions provided by your application) to determine whether the specified column in the row currently being checked equals the specified string. 
  4159. Comparison records often form part of a logical descriptor record, which is a descriptor record of type typeLogicalDescriptor that specifies a logical expression—that is, an expression that the Apple Event Manager evaluates to either TRUE or FALSE. The logical expression is constructed from a logical operator (one of the Boolean operators AND, OR, or NOT) and a list of logical terms to which the operator is applied. Each logical term in the list can be either another logical descriptor record or a comparison descriptor record. If the logical operator is AND or OR, the list can contain any number of logical terms, and the logical operator is applied to all the terms in the list. For example, the logical descriptor data shown in Figure 2-25 on page 2-138 consists of the logical operator AND and a list of logical terms that contains two comparison descriptor records. The entire logical descriptor record corresponds to the logical expression “the First Name column equals ‘John’ AND the Last Name column equals ‘Chapman’.” If the logical operator is NOT, the list must contain a single term. 
  4160. A logical descriptor record is a coerced AE record that consists of two descriptor records specified by the following keywords:
  4161. Keyword        Description
  4162. keyAELogicalOperator        A descriptor record of typeEnumeration that identifies the logical operator to be applied to the logical terms. 
  4163. keyAELogicalTerms        A descriptor record of typeAEList that lists the descriptor records to which the logical operator is to be applied. The list can include logical descriptor records, comparison descriptor records, or both. keyAELogicalOperator 
  4164. You can specify one of these constants for the data in a descriptor record specified by the keyword keyAELogicalOperator:
  4165. Constant        Logical operator
  4166. kAEAND        AND 
  4167. kAEOR        OR 
  4168. kAENOT        NOT 
  4169. You can use the CreateLogicalDescriptor function to create a logical descriptor record, or you can create an AE record and use the AECoerceDesc function to coerce it to a comparison descriptor record. Listing 2-28 provides shows an application-defined function that adds two comparison descriptor records to a descriptor list, then uses the CreateLogicalDescriptor function to create a logical descriptor record whose logical terms consists of the two comparison descriptor records.
  4170. Creating a logical descriptor record
  4171. FUNCTION MyCreateLogicalDescRec(compDesc1, compDesc2: AEDesc;
  4172.                                         logicalOperator: DescType;
  4173.                                         VAR logicalDesc: AEDesc): OSErr;
  4174. VAR
  4175.     logicalTermsList: AEDescList;
  4176.     myErr:                         OSErr;
  4177. BEGIN
  4178.     {create a logical descriptor record that contains two }
  4179.     { comparison descriptor records}
  4180.     {first create a list}
  4181.     myErr := AECreateList(NIL, 0, FALSE, logicalTermsList);
  4182.     myErr := AEPutDesc(logicalTermsList, 1, compDesc1);
  4183.     myErr := AEPutDesc(logicalTermsList, 2, compDesc2);
  4184.     myErr := AEDisposeDesc(compDesc1);
  4185.     myErr := AEDisposeDesc(compDesc2);
  4186.     myErr := CreateLogicalDescriptor(logicalTermsList,
  4187.                                                  logicalOperator, TRUE,
  4188.                                                  logicalDesc);
  4189.     MyCreateLogicalDescRec := myErr;
  4190.     {add your own error checking}
  4191. END; 
  4192. The key data for the keyTest key form always consists of a logical descriptor record whose logical terms include whatever combination of logical descriptor records and/or comparison descriptor records is appropriate for the tests your application might need to apply to the elements in a container. Figure 2-24 shows four object specifier records that specify the container hierarchy for the first row in the table “MyAddresses” of the database “GigaBase” that meets a test. The object specifier record on the left in Figure 2-24 specifies the first row contained in the set of rows that form its container. The container for the first row is specified by an object specifier record for a set of rows that meet a test. The two object specifier records on the right in Figure 2-24 specify the table named “MyAddresses,” which contains the rows to be tested, in the database named “GigaBase.” 
  4193. The container hierachy for the first row in a document that meets a test
  4194. A logical descriptor record that specifies a test  
  4195. The key form for the second object specifier record in Figure 2-24, which specifies a set of lines that meet a test, is formTest. The corresponding key data consists of the logical descriptor record illustrated in Figure 2-25, which applies the logical operator AND to two logical terms: a comparison descriptor record that specifies all the rows in the container (that is, in the table “MyAddresses”) in which the column named “First Name” equals “John,” and another comparison descriptor record that specifies all the rows in which the column named “First Name” equals “Chapman.” Only the rows in the table “MyAddresses” for which both comparison descriptor records evaluate as TRUE pass the test.
  4196. Note that the keyword-specified descriptor record with the key word keyAEObject1 in each comparison record shown in Figure 2-25 consists of an object specifier record. The container for each of these object specifier records is specified by a descriptor record of typeObjectBeingExamined, which functions much like a variable that changes as the Apple Event Manager tests successive rows in the table. The Apple event object specified by each of these object specifier records consists of a column in the row, which the Apple Event Manager (with the help of your object comparison function) compares to the string in the keyword-specified descriptor record with the keyword keyAEObject2 using the comparison operator in the keyword-specified descriptor record with the keyword keyAECompOperator.
  4197. Listing 2-29 uses the application-defined functions shown in Listing 2-26, Listing 2-27, and Listing 2-28 to build the complex object specifier record illustrated in Figure 2-24 and Figure 2-25.
  4198. Creating a complex object specifier record
  4199. FUNCTION MyCreateCompleteObjSpecRec (VAR theResultObj: AEDesc): OSErr;
  4200. VAR
  4201.     nullContainer, databaseContainer, tableContainer:                                                                     AEDesc;
  4202.     compDesc1, compDesc2:                                                                     AEDesc;
  4203.     logicalTestDesc, rowTestContainer, rowOffset:                                                                     AEDesc;
  4204.     myErr:                                                                     OSErr;
  4205. BEGIN
  4206.     {create a null container}
  4207.     myErr := AECreateDesc(typeNull, NIL, 0, nullContainer);
  4208.     {create a container for the database}
  4209.     myErr := MyCreateFormNameObjSpecifier(cDatabase, nullContainer,
  4210.                                                          \qGigaBase\q, databaseContainer);
  4211.     {create a container for the table}
  4212.     myErr := MyCreateFormNameObjSpecifier(cTable, databaseContainer, 
  4213.                                                         \qMyAddresses\q, tableContainer);
  4214.     {create a container for the row--an object spec record that }
  4215.     { specifies a test (the row whose First Name column = \qJohn\q and }
  4216.     { Last Name column = \qChapman\q)}
  4217.  
  4218.     {create the first comparison descriptor record}
  4219.     myErr := MyCreateComparisonDescRec(compDesc1, \qFirst Name\q, \qJohn\q); 
  4220.     {create the second comparison descriptor record}
  4221.     myErr := MyCreateComparisonDescRec(compDesc2, \qLast Name\q, \qChapman\q); 
  4222.  
  4223.     {create the logical descriptor record}
  4224.     myErr := MyCreateLogicalDescRec(compDesc1, compDesc2, kAEAND, 
  4225.                                                 logicalTestDesc);
  4226.  
  4227.     {now create the object spec record that specifies the test}
  4228.     myErr := CreateObjSpecifier(cRow, tableContainer, formTest,
  4229.                                          logicalTestDesc, TRUE, rowTestContainer);
  4230.  
  4231.     {create the object spec record for the Apple event object}
  4232.     {first, create the descriptor record for the key data}
  4233.     myErr := CreateOffsetDescriptor (1, rowOffset);
  4234.     {now create the object spec record}
  4235.     myErr := CreateObjSpecifier (cRow, rowTestContainer, 
  4236.                                             formAbsolutePosition, rowOffset, 
  4237.                                             TRUE, theResultObj);
  4238.     MyCreateCompleteObjSpecRec := myErr;
  4239.     {add your own error checking}
  4240. END;
  4241. The MyCreateCompleteObjSpecRec function shown in Listing 2-29 begins by using AECreateDesc to create a null descriptor record, then uses the MyCreateFormNameObjSpecifier function (shown in Listing 2-26) to specify the default container for the database named “GigaBase.” The code then calls the MyCreateFormNameObjSpecifier function again, this time passing the object specifier record for “GigaBase” to specify the container for the table “MyAddresses.” The next two calls are both to the MyCreateComparisonDescRec function (shown in Listing 2-27), which creates the comparison descriptor records that allow the Apple Event Manager to compare the First Name column and Last Name column to the names “John” and “Chapman,” respectively. The next call passes these two comparison descriptor records to the MyCreateLogicalDescRec function (shown in Listing 2-28) in the compDesc1 and compDesc2 variables. Now all the components of the logical descriptor record are ready to assemble. The next call, to CreateObjSpecifier, specifies the logical descriptor record in the logicalTestDesc variable as the key data for the object specifier record that specifies the test. A call to the Apple Event Manager routine CreateOffsetDescriptor then creates an offset descriptor record that contains the integer 1. Finally, the code passes the offset descriptor record to the CreateObjSpecifier function in the rowOffset variable to create the final object specifier record, which describes the requested row as the first row that passes the test.
  4242. The CreateOffsetDescriptor function creates a descriptor record of type typeLongInteger that can be used as the key data with a key form of formAbsolutePosition to indicate an element’s offset within its container. A positive integer indicates an offset from the beginning of the container (the first element has an offset of 1), and a negative integer indiates an offset from the end of the container (the last element has an offset of -1). Using CreateOffsetDescriptor accomplishes the same thing as setting a variable to an integer and passing the variable to AECreateDesc to create a descriptor record of type typeLongInteger.  
  4243. Specifying a Range
  4244. The key form formRange allows you to specify key data that identifies a range of elements in the specified container. To specify the key data for a key form of formRange, your application must create a range data descriptor record, which is a descriptor record of type typeRangDescriptor that the Apple Event Manager uses to identify the two Apple event objects that specify the beginning and end of a range of elements. A range data descriptor record is a coerced AE record that consists of two keyword-specified descriptor records with the following keywords: 
  4245. Keyword        Description
  4246. keyAERangeStart        An object specifier record that identifies the first Apple event object in the desired range. 
  4247. keyAERangeStop        An object specifier record that identifies the last Apple event object in the desired range. 
  4248. The elements that specify the beginning and end of the range, which are known as boundary objects, do not have to belong to the same object class as the elements in the range itself. For example, an object specifier record for a range of text in a document could specify the table named “Summary of Sales, 1991” as the first boundary object and the figure named “Best Selling Widget for 1991” as the second boundary object for a range that consists of all the text between the table and the figure. Any word processor that keeps track of the relative positions of text, tables, and figures would be capable of supporting such a request.
  4249. You can use the CreateRangeDescriptor function to create a range data descriptor record, or you can create an AE record and use AECoerceDesc to coerce it to a range data descriptor record. Listing 2-30 provides an example of an application-defined routine that creates two object specifier records, then uses the CreateRangeDescriptor function to add them to a range data descriptor record.
  4250. Creating a range descriptor record
  4251. FUNCTION MyCreateRangeDescriptor (rangeDescRec: AEDesc): OSErr;
  4252. VAR
  4253.     rangeStart:                             AEDesc;
  4254.     rangeEnd:                            AEDesc;
  4255.     docContainer:                            AEDesc;
  4256.     tableNameDescRec    :                        AEDesc;
  4257.     figureNameDescRec    :                        AEDesc;
  4258.     myErr:                            OSErr;
  4259. BEGIN
  4260. {create the object specifier record for the start of the range }
  4261. { (the table named 'Summary of Sales' in 'MyDoc' document)}
  4262.     {create the container for the document}
  4263.     myErr := MyCreateDocContainer(docContainer, 'MyDoc');
  4264.     {create the object specifier record}
  4265.     myErr := MyCreateNameDescRec(tableNameDescRec, 'Summary of Sales, 1991');
  4266.     myErr := CreateObjSpecifier(cTable, docContainer, formName,
  4267.                                      tableNameDescRec, TRUE, rangeStart);
  4268.     
  4269. {create the object specifier record for the end of the range }
  4270. { (the figure named 'Best Selling Widgets...' in 'MyDoc') }
  4271.     myErr := MyCreateNameDescRec(figureNameDescRec, 
  4272.                                         'Best Selling Widgets for 1991');
  4273.     myErr := CreateObjSpecifier(cFigure, docContainer, formName,
  4274.                                          figureNameDescRec, TRUE, rangeEnd);
  4275.  
  4276. {now create the range descriptor record}
  4277.     myErr := CreateRangeDescriptor(rangeStart, rangeStop, TRUE, rangeDescRec);
  4278.     MyCreateRangeDescriptor := myErr;
  4279. {add your own error checking}
  4280. END;
  4281. After using two application-defined routines to create an object specifier record for a document and a descriptor record for a table’s name, Listing 2-30 uses the CreateObjSpecifier function to create an object specifier record that identifies the beginning of the range. The parameters to CreateObjSpecifier specify that the beginning of the range is an Apple event object of the object class cTable in the container specified by the docContainer variable, with a key form of formName and key data that identifies the table by name. A second call to CreateObjSpecifier creates the object specifier record that identifies the end of the range—an Apple event object of the cFigure object class in the container specified by the docContainer variable, with a key form of formName and key data that identifies the figure by name.
  4282. Finally, the code in Listing 2-30 uses the CreateRangeDescriptor function to create the range descriptor record, specifying the two previously created object specifier records as the beginning and end of the range.      
  4283. Sending an Apple Event
  4284. To send an Apple event, you first create an Apple event, add parameters and attributes to the Apple event, and then use the AESend function to send it. 
  4285. When you send an Apple event, you specify various options to indicate how the server should handle the Apple event. You request a user interaction level from the server and specify whether the server can directly switch to the foreground if user interaction is needed, whether your application is willing to wait for a reply Apple event, whether reconnection is allowed, and whether your application wants a return receipt for the Apple event. 
  4286. You specify these options by setting flags in the sendMode parameter for AESend. Here are the constants that represent these flags:
  4287. CONST         kAENoReply                        = $00000001; {client doesn't want reply}
  4288.         kAEQueueReply                        = $00000002; {client wants server to }
  4289.                                                  { reply in event queue}
  4290.         kAEWaitReply                        = $00000003; {client wants a reply and }
  4291.                                                  { will give up processor}
  4292.         kAENeverInteract                        = $00000010; {server application }
  4293.                                                  { should not interact }
  4294.                                                  { with user for this }
  4295.                                                  { Apple event}
  4296.         kAECanInteract                        = $00000020; {server may interact with }
  4297.                                                  { user for this Apple }
  4298.                                                  { event to supply } 
  4299.                                                  { information}
  4300.         kAEAlwaysInteract                        = $00000030; {server may interact with }
  4301.                                                 { user for this Apple }
  4302.                                                 { event even if no }
  4303.                                                 { information                 is required}
  4304.  
  4305.         kAECanSwitchLayer                        = $00000040; {server should come }
  4306.                                                  { directly to foreground }
  4307.                                                  { when appropriate}
  4308.         kAEDontReconnect                        = $00000080; {don't reconnect if there}
  4309.                                                  { is a PPC sessClosedErr}
  4310.         kAEWantReceipt                        = nReturnReceipt; {client wants return }
  4311.                                                         { receipt}
  4312. If your application wants a reply Apple event, specify the kAEQueueReply or kAEWaitReply flag. If your application wants to receive the reply Apple event in its event queue, use kAEQueueReply. If your application wants to receive the reply Apple event in the reply parameter for AESend and is willing to give up the processor while waiting for the reply, use kAEWaitReply. If your application does not want a reply Apple event and does not need to wait for the server to handle the Apple event, specify kNoReply. 
  4313. If your application specifies kAENoReply or kAEQueueReply, the AESend function returns immediately after using the Event Manager to send the event. In this case, a noErr result code from AESend indicates that the Apple event was successfully sent by the Event Manager; it does not mean that the server accepted or handled the Apple event. 
  4314. When AESend returns, the reply parameter does not contain valid data if your application specifies kAENoReply or kAEQueueReply. The kAENoReply flag indicates that the Apple Event Manager will not return the reply Apple event to your application. The kAEQueueReply flag indicates that your application wants to receive the reply via its event queue rather than the reply parameter of AESend.
  4315. If your application specifies kAEWaitReply, the Apple Event Manager uses the Event Manager to send the event. The Apple Event Manager then calls the WaitNextEvent function on behalf of your application, causing your application to yield the processor. This gives the server application a chance to receive and handle the Apple event. Your application continues to yield the processor until the server handles the Apple event or the request times out.
  4316. You use one of the three flags—kAENeverInteract, kAECanInteract, and kAEAlwaysInteract—to specify whether the server should interact with the user when handling the Apple event. Specify kAENeverInteract if the server should not interact with the user when handling the Apple event. You might specify this constant if you don’t want the user to be interrupted while the server is handling the Apple event.
  4317. Use the kAECanInteract flag if the server should interact with the user when the user needs to supply information to the server. Use the kAEAlwaysInteract flag if the server should interact with the user whenever the server normally asks a user to confirm a decision or interact in any other way, even if no additional information is needed from the user. Note that it is the responsibility of the server and client applications to agree on how to interpret the kAEAlwaysInteract flag. 
  4318. If the client application does not set any one of the user interaction flags, the Apple Event Manager sets a default, depending on the location of the target of the Apple event. If the server application is on a remote computer, the Apple Event Manager sets the kAENeverInteract flag as the default. If the target of the Apple event is on the local machine, the Apple Event Manager sets the kAECanInteract flag as the default.
  4319. The server application should call AEInteractWithUser if it needs to interact with the user. If both the client and the server allow user interaction, the Apple Event Manager attempts to bring the server to the foreground if it is not already the foreground process. If both the kAECanSwitchLayer and the kAEWaitReply flags are set, and if the client application is the active application on the local machine, the Apple Event Manager brings the server application directly to the front. Otherwise, the Apple Event Manager posts a notification request to ask the user to bring the server application to the front, regardless of whether the kAECanSwitchLayer flag is set. This ensures that the user will not be interrupted by an unexpected application switch. 
  4320. You should specify the kAECanSwitchLayer flag only when the client and server applications reside on the same computer. In general, you should not set this flag if it would be confusing or inconvenient to the user for the server application to come to the front unexpectedly.
  4321. Specify the kAEDontReconnect flag if the Apple Event Manager should not reconnect if it receives a session closed error from the PPC Toolbox. If you don’t set this flag, the Apple Event Manager automatically attempts to reconnect and reestablish the session.
  4322. Specify the kAEWantReceipt flag if your application wants notification that the server application has accepted the Apple event. If you specify this flag and the server application does not accept the Apple event within the time specified by the timeOutInTicks parameter to AESend, the AESend function will return a timeout error.
  4323. Listing 2-31 illustrates how to send a Multiply event (an imaginary Apple event for multiplying two long integers). It first creates an Apple event, adds parameters containing the numbers to multiply, then sends it, specifying various options. It also illustrates how to handle the reply Apple event that contains the result.
  4324. If you want to send Apple events, your application must set flags in its \qSIZE\q resource that indicate that it can handle high-level events, and must provide handlers for the required Apple events. See “Accepting an Apple Event” on page 2-60 for information on setting the appropriate flags in the \qSIZE\q resource, and “Handling the Required Apple Events” on page 2-72 for information supporting the required Apple events.<36pt\>\x12 <8bat\>u
  4325. Sending an Apple event
  4326. FUNCTION MySendMultiplyEvent (serverAddress: AEAddressDesc;
  4327.                                         firstOperand: LongInt; 
  4328.                                         secondOperand:                     LongInt; 
  4329.                                         VAR replyResultLongInt: LongInt): 
  4330.                                         OSErr;
  4331. CONST
  4332.     kArithmeticClass                         =    'ARTH';             {event class for arithmetic }
  4333.                                             { Apple events}
  4334.     kMultiplyEventID                         =    'MULT';             {event ID for Multiply event}
  4335.     keyMultOperand1                        =     'OPN1';            {keyword for first parameter}
  4336.     keyMultOperand2                        =     'OPN2';             {keyword for second parameter}
  4337. VAR
  4338.     theAppleEvent:                         AppleEvent;
  4339.     reply:                         AppleEvent;
  4340.     returnedType:                        DescType;
  4341.     actualSize:                         LongInt;
  4342.     myErr:                        OSErr;
  4343.     errStr:                        Str255;
  4344.     errNumber:                        LongInt;
  4345. BEGIN
  4346.     myErr := AECreateAppleEvent(kArithmeticClass, 
  4347.                                          kMultiplyEventID, serverAddress, 
  4348.                                          kAutoGenerateReturnID,
  4349.                                          kAnyTransactionID, theAppleEvent);
  4350.     IF myErr <> noErr THEN
  4351.         DoError(myErr); {failed to create the event}        
  4352.     {add the first operand}
  4353.     myErr := AEPutParamPtr(theAppleEvent, keyMultOperand1, 
  4354.                                   typeLongInteger, @firstOperand, 
  4355.                                     SizeOf(firstOperand));
  4356.     IF myErr <> noErr THEN
  4357.         DoError(myErr);                     {failed to add first parameter--be sure }
  4358.                              { to dispose of the event before leaving }
  4359.                              { routine}
  4360.     {add the second operand with the proper keyword}
  4361.     myErr := AEPutParamPtr(theAppleEvent, keyMultOperand2, 
  4362.                                   typeLongInteger, @secondOperand, 
  4363.                                   SizeOf(secondOperand));
  4364.  
  4365.  
  4366.     IF myErr <> noErr THEN
  4367.         DoError(myErr);                        {be sure to dispose of the event and }
  4368.                                 { first parameter before leaving routine}
  4369.     myErr := AESend(theAppleEvent, reply, kAEWaitReply +             
  4370.                          kAENeverInteract, kAENormalPriority, 120, 
  4371.                          @myIdleFunction, NIL);
  4372.     IF myErr = noErr THEN {Apple event successfully sent}
  4373.     BEGIN              {check whether it was successfully handled-- }
  4374.                { get result code returned by the server's handler}
  4375.         myErr := AEGetParamPtr(reply, keyErrorNumber, 
  4376.                                       typeLongInteger, returnedType, 
  4377.                                       @errNumber, Sizeof(errNumber), 
  4378.                                       actualSize);
  4379.         IF (myErr = errAEDescNotFound) OR (errNumber = noErr) THEN
  4380.         {if keyErrorNumber doesn't exist or server returned noErr}
  4381.         BEGIN                { then the Apple event was successfully }
  4382.                         { handled–– the reply Apple event contains }
  4383.                         { the result in the direct parameter}
  4384.             myErr := AEGetParamPtr(reply, keyDirectObject, 
  4385.                                           typeLongInteger, returnedType, 
  4386.                                           @replyResultLongInt, 
  4387.                                           SizeOf(replyResultLongInt), 
  4388.                                           actualSize);
  4389.             MySendMultiplyEvent := noErr; 
  4390.             Exit(MySendMultiplyEvent);
  4391.         END
  4392.         ELSE
  4393.         BEGIN            {server returned an error, so get error string}
  4394.             myErr := AEGetParamPtr(reply, keyErrorString, typeChar, 
  4395.                                             returnedType, @errStr, 
  4396.                                           Sizeof(errStr), actualSize);    
  4397.             IF myErr = noErr THEN
  4398.                 MyDisplayError(errStr);
  4399.         END;
  4400.     END
  4401.     ELSE
  4402.     BEGIN
  4403.     {the Apple event wasn't successfully dispatched, }
  4404.     { the request timed out, the user canceled, or other error} 
  4405.     END;
  4406. MySendMultiplyEvent := myErr;
  4407. END;
  4408. The code in Listing 2-31 first creates an Apple event with kArithmeticClass as the event class and kMultiplyEventID as the event ID. It also specifies the server of the Apple event. See “Specifying a Target Address” on page 2-116 for information on specifying a target address, and see “Creating an Apple Event” on page 2-110 for more information on how to create an Apple event.
  4409. The Multiply event shown in Listing 2-31 contains two parameters, each of which specifies a number to multiply. See “Adding Parameters to an Apple Event” on page 2-111 for examples of how to specify the parameters for the AEPutParamPtr function. 
  4410. After adding the parameters to the event, the code uses AESend to send the event. The first parameter to AESend specifies the Apple event to send—in this example, the Multiply event. The next parameter specifies the reply Apple event. 
  4411. This example specifies kAEWaitReply in the third parameter, indicating that the client is willing to yield the processor for the specified timeout value (120 ticks, or 2 seconds). The kAENeverInteract flag indicates that the server should not interact with the user when processing the Apple event. The Multiply event is sent using normal priority, meaning it is placed at the end of the event queue. You can specify the kAEHighPriority flag to place the event in the front of the event queue, but this is not recommended.
  4412. The next to last parameter specifies the address of an idle function. If you specify kAEWaitReply, you should provide an idle function. This function should process any update events, null events, operating-system events, or activate events that occur while your application is waiting for a reply. See “Writing an Idle Function” on page 2-150 for sample code that shows an idle function. 
  4413. The last parameter to AESend specifies a filter function. You can supply a filter function to filter high-level events that your application may receive while waiting for a reply Apple event. You can specify NIL for this parameter if you do not need to filter high-level events while waiting for a reply. See “Writing a Reply Filter Function” on page 2-152 for more information. 
  4414. If your application specified kAEWaitReply and AESend returns a noErr result code, the result code indicates that the Apple event was sent succesfully, not that the server has completed the requested action successfully. Therefore, you should find out whether a result code was returned from the handler by checking the reply Apple event for the existence of the parameter whose keyword is keyErrorNumber. If the keyErrorNumber parameter does not exist or contains the noErr result code, you can use AEGetParamPtr to get the parameter you’re interested in from the reply Apple event. 
  4415. The code in Listing 2-31 checks the function result of AESend. If AESend returns noErr, the code then checks the keyErrorNumber parameter of the reply Apple event to determine whether the server successfully handled the Apple event. If this parameter exists and indicates that an error occurred, then the code gets the error string out of the keyErrorString parameter. Otherwise, the server performed the request, and the reply Apple event contains the answer to the multiplication request.
  4416. When you have finished using the Apple event specified in the AESend function and finished with the reply Apple event, you must dispose of their descriptor records using the AEDisposeDesc function.
  4417. If your application sends Apple events to itself using a typeProcessSerialNumber address descriptor record with the value kCurrentProcess, the Apple Event Manager jumps directly to the appropriate Apple event handler without going through the normal event-processing sequence. As a result, your application will not run appreciably more slowly when it sends Apple events to itself. Because the Apple Event Manager calls your application’s Apple event handlers directly, without going through the PPC Toolbox, Apple events your application sends to itself do not appear in your application’s high-level event queue.<36pt\>\x12 <8bat\>s   
  4418. Dealing With Timeouts
  4419. When your application calls AESend and chooses to wait for the server application to handle the Apple event, it can also specify the maximum amount of time that it is willing to wait for a response. You can specify a timeout value in the timeOutInTicks parameter to AESend. You can either specify a particular length of time, in ticks, that your application is willing to wait, or you can specify the kNoTimeOut constant or the kAEDefaultTimeout constant. 
  4420. Use the kNoTimeOut constant to indicate that your application is willing to wait forever for a response from the server. You should use this value only if you are sure that the server will respond in a reasonable amount of time. You should also implement a method of checking if the user wants to cancel. The idle function that you specify as a parameter to AESend should check the event queue for any instances of Command-period and immediately return TRUE as its function result if it finds a request to cancel in the event queue.
  4421. Use the kAEDefaultTimeout constant if you want the Apple Event Manager to use a default value for the timeout value. The Apple Event Manager uses a timeout value of about one minute if you specify this constant.
  4422. Note that if you set the kAEWaitReply flag and the server doesn’t have a handler for the Apple event, the server immediately returns the errAEEventNotHandled result code.
  4423. If the server doesn’t respond within the length of time specified by the timeout value, AESend returns the errAETimeout result code and a reply Apple event that does not contain any data. This result code does not necessarily mean that the server failed to perform the requested action; it only means that the server did not complete processing within the specified time. The server might still be processing the Apple event, and it might still send a reply.
  4424. If the server finishes processing the Apple event sometime after the time specified in the timeout parameter has expired, it returns a reply Apple event to AEProcessAppleEvent. The Apple Event Manager then adds the actual data to the reply. 
  4425. This means your application can continue to check the reply Apple event to see if the server has responded, even after the time expires. If the server has not yet sent the reply when the client attempts to extract data from the reply Apple event, the Apple Event Manager functions return the errAEReplyNotArrived result code. After the reply Apple event returns from the server, the client can extract the data in the reply.
  4426. Additionally, the server can determine the timeout value specified by the client by examining the keyTimeoutAttr attribute in the Apple event. You can use the value of this attribute as a rough estimate of how much time your handler has to respond. You can assume that your handler has less time to respond than the timeout value, because transmitting the Apple event uses some of the available time, as does transmitting the reply Apple event back to the client, and the event may have been in the queue for a while already.
  4427. If your handler needs more time than is specified in the keyTimeoutAttr attribute, you can reset the timer by using the AEResetTimer function. This function resets the timeout value of an Apple event to its starting value.
  4428. Writing an Idle Function
  4429. This section describes how to write an idle function when using the AESend or AEInteractWithUser function.
  4430. When your application sends an Apple event, you can wait for the server application to receive and finish handling the Apple event, or you can continue processing. If your application chooses to continue processing, the AESend function returns immediately after using the Event Manager to send the event. If your application chooses to wait for the server to handle the event, the AESend function does not return until either the server application finishes handling the Apple event or a specified amount of time expires.
  4431. Your application specifies its preferences by setting flags in the sendMode parameter to AESend. Your application can specify kAENoReply if it does not want to receive a reply, kAEQueueReply if it wants to receive the reply in its event queue, or kAEWaitReply if it wants the reply returned in the reply parameter of AESend and is willing to give up the processor while waiting for the reply.
  4432. If your application specifies the kAEWaitReply flag, the AESend function calls WaitNextEvent on behalf of your application. This yields the processor to other processes, so that the server has an opportunity to receive and process the Apple event sent by your application. While your application is waiting for a reply, it cannot receive events unless it provides an idle function.
  4433. If your application provides a pointer to an idle function as a parameter to the AESend function, AESend calls your idle function whenever an update event, null event, operating-system event, or activate event is received for your application. Your application can process high-level events that it receives while waiting for a reply by providing a reply filter function. See the next section, “Writing a Reply Filter Function,” for more information.
  4434. In a similar manner, when your application calls the AEInteractWithUser function, your application can also yield the processor. If AEInteractWithUser needs to post a notification request to bring your application to the front, your application yields the processor until the user brings your application to the front. To receive events while waiting for the user to bring your application to the front, you must provide an idle function.
  4435. If your application provides a pointer to an idle function as a parameter to the AEInteractWithUser function, AEInteractWithUser calls your idle function whenever an update event, null event, operating-system event, or activate event is received for your application.
  4436. An idle function must use this syntax:
  4437. FUNCTION MyIdleFunction (VAR theEventRecord: EventRecord;
  4438.                                  VAR sleepTime:         LongInt;
  4439.                                  VAR mouseRgn: RgnHandle): Boolean;
  4440. The parameter theEventRecord is the event record of the event to process. The sleepTime parameter and mouseRgn parameter are values that your idle function sets the first time it is called; thereafter they contain the values your function set. Your idle function should return a Boolean value that indicates whether your application wishes to continue waiting. Set the function result to TRUE if your application is no longer willing to wait for a reply from the server or for the user to bring the application to the front. Set the function result to FALSE if your application is still willing to wait.
  4441. The first time your idle function is called, you may set the values for the sleepTime and mouseRgn parameters. These parameters are used in the same way as the sleep and mouseRgn parameters of the WaitNextEvent function. Specify in the sleepTime parameter the amount of time (in ticks) during which your application agrees to relinquish the processor if no events are pending for it.
  4442. In the mouseRgn parameter, you specify a screen region that determines the conditions in which your application is to receive notice of mouse-moved events. Your idle function receives mouse-moved events only if your application is the front application and the mouse strays outside the region you specify.
  4443. Your idle function receives only update events, null events, operating-system events, and activate events. When your idle function receives a null event, it can use the idle time to update a status dialog box, animate cursors, or perform similar tasks. If your idle function receives any of the other events, it should handle the event as it normally would if received in its event loop.
  4444. Listing 2-32 shows an example of an idle function that can be used as an idle function for AESend or AEInteractWithUser. The idle function processes update events, null events, operating-system events, and activate events. The first time the function is called it receives a null event. At this time, it sets the sleepTime and mouseRgn parameters. The function continues to process events until the server finishes handling the Apple event or the user brings the application to the front.
  4445. Your application should implement a method of checking to see if the user wants to cancel. The MyCancelInQueue function in Listing 2-32 checks the event queue for any instances of Command-period and immediately returns TRUE as its function result if it finds a request to cancel in the event queue.
  4446. An idle function
  4447. FUNCTION MyIdleFunction (VAR event: EventRecord;
  4448.                                   VAR sleeptime: LongInt;
  4449.                                   VAR mouseRgn: RgnHandle): Boolean;
  4450. VAR
  4451.     hiByte: Char;
  4452.     myErr:  OSErr;
  4453. BEGIN
  4454.     MyIdleFunction := FALSE;
  4455.     {the MyCancelInQueue function checks for Command-period}
  4456.     IF MyCancelInQueue THEN
  4457.         BEGIN                            
  4458.             MyIdleFunction := TRUE;
  4459.             Exit(MyIdleFunction);
  4460.         END;
  4461.     CASE event.what OF
  4462.         updateEvt,
  4463.         activateEvt,                    {every idle function should handle }
  4464.         kOSEvent:                    { these kinds of events}
  4465.             BEGIN
  4466.                 AdjustCursor(event.where, gCursorRgn);    
  4467.                 DoEvent(event);
  4468.             END;
  4469.         nullEvent:
  4470.             BEGIN
  4471.                 {set the sleepTime and mouseRgn parameters}
  4472.                 mouseRgn := gCursorRgn;
  4473.                 sleeptime := 10;                        {use the correct value for your }
  4474.                                         { app}                            
  4475.                 DoIdle;                        {the application's idle handling}
  4476.             END 
  4477.     END; {CASE}
  4478. END;
  4479. Writing a Reply Filter Function
  4480. If your application calls AESend and chooses to yield the processor to other processes while waiting for a reply, you can provide an idle function to process update, null, operating-system, and activate events, and you can provide a reply filter function to process high-level events. The previous section describes how an idle function processes events.
  4481. Your reply filter function can process any high-level events that it is willing to handle while waiting for a reply Apple event. For example, your application can choose to handle Apple events from other processes while waiting. Note, however, that your application must maintain any necessary state information. Your reply filter function must not accept any Apple events that can change the state of your application and make it impossible to return to its previous state.
  4482. A reply filter function must use this syntax:
  4483. FUNCTION MyWaitReplyFilter (VAR theEventRecord: EventRecord;
  4484.                                         returnID: LongInt; 
  4485.                                      transactionID: LongInt;
  4486.                                     sender: AEAddressDesc): Boolean;
  4487. The parameter theEventRecord is the event record for a high-level event. The next three parameters contain valid information only if the event is an Apple event. The returnID parameter is the return ID for the Apple event. The transactionID parameter is the transaction ID for the Apple event. The sender parameter contains the address of the application or process that sent the Apple event.
  4488. Your reply filter function should return TRUE as the function result if you want to accept the Apple event; otherwise it should return FALSE. If your filter function returns TRUE, the Apple Event Manager calls the AEProcessAppleEvent function on behalf of your application, and your handler routine is called to process the Apple event. In this case, make sure your handler does not get called while it is still being used by an earlier call.
  4489. Writing and Installing Coercion Handlers
  4490. When your application extracts data from a parameter, it can request that the Apple Event Manager return the data using a descriptor type that is different from the original descriptor type. For example, when extracting data from the direct parameter of the Open Documents event, you can request that the alias records be returned as file system specification records. The Apple Event Manager can automatically coerce many different types of data from one to another. Table 2-1 on page 2-156 shows descriptor types and the kinds of coercion that the Apple Event Manager can perform.
  4491. You can also provide your own routines, referred to as coercion handlers, to coerce data into any other descriptor type. To install your own coercion handlers, use the AEInstallCoercionHandler function. You specify as parameters to this function
  4492. n    the descriptor type of the data coerced by the handler
  4493. n    the descriptor type of the resulting data
  4494. n    the address of the coercion handler for this descriptor type
  4495. n    a reference constant
  4496. n    a Boolean value that indicates whether your coercion handler expects the data to be specified as a descriptor record or as a pointer to the actual data
  4497. n    a Boolean value that indicates whether your coercion handler should be added to your application’s coercion table or the system coercion table
  4498. The system coercion table is a table in the system heap that contains handlers that are available to all applications and processes running on the same computer. The handlers in your application’s coercion table are available only to your application. When the Apple Event Manager is attempting to coerce data, it first looks for a coercion handler in your application’s coercion table. If it cannot find a handler for the descriptor type, it looks in the system coercion table for a handler. If it doesn’t find a handler there either, it returns the errAEHandlerNotFound result code.
  4499. If you add a handler to the system coercion table, the handler that you specify should reside in the system heap. If there was already an entry in the system coercion table for the same descriptor type, it is replaced. Therefore, if there is an entry in the system coercion table for the same descriptor type, you should chain it to your system coercion handler as explained in “Creating and Managing the Coercion Handler Dispatch Tables” on page 2-247.
  4500. When an application calls a system coercion handler, the A5 register is set up for the calling application. For this reason, if you provide a system coercion handler, it should never use A5 global variables or anything that depends on a particular context; otherwise, the application that calls the system coercion handler may crash.<36pt\>\x12 <8bat\>u
  4501. You can provide a coercion handler that expects to receive the data in a descriptor record or a buffer referred to by a pointer. When you install your coercion handler, you specify how your handler wishes to receive the data. It’s more efficient for the Apple Event Manager to provide your coercion handler with a pointer to the data so, whenever possible, you should write your coercion handler so that it can accept a pointer to the data.
  4502. A coercion handler that accepts a pointer to data must be a function with the following syntax:
  4503. FUNCTION MyCoercePtr (typeCode: DescType; dataPtr: Ptr; 
  4504.                              dataSize: Size; toType: DescType; 
  4505.                              handlerRefcon: LongInt;
  4506.                              VAR result: AEDesc): OSErr; 
  4507. The typeCode parameter is the descriptor type of the original data. The dataPtr parameter is a pointer to the data to coerce; the dataSize parameter is the length, in bytes, of the data. The toType parameter is the desired descriptor type of the resulting data. The handlerRefcon parameter is a reference constant that is stored in the coercion table entry for the handler and passed to the handler by the Apple Event Manager whenever the handler is called. The result parameter is the resulting descriptor record returned by your coercion handler.
  4508. Your coercion handler should coerce the data to the desired descriptor type and return the resulting data in the descriptor record specified by the result parameter. Your handler should return the noErr result code if your handler successfully performs the coercion, and a nonzero result code otherwise.
  4509. A coercion handler that accepts a descriptor record must be a function with the following syntax:
  4510. FUNCTION MyCoerceDesc (theAEDesc: AEDesc; toType: DescType;
  4511.                                 handlerRefcon: LongInt;
  4512.                                  VAR result: AEDesc): OSErr;
  4513. The parameter theAEDesc is the descriptor record that contains the data to be coerced. The toType parameter is the descriptor type of the resulting data. The handlerRefcon parameter is a reference constant that is stored in the coercion table entry for the handler and passed to the handler by the Apple Event Manager whenever the handler is called. The result parameter is the resulting descriptor record.
  4514. Your coercion handler should coerce the data in the descriptor record to the desired descriptor type and return the resulting data in the descriptor record specified by the result parameter. Your handler should return an appropriate result code.
  4515. Table 2-1 lists the descriptor types for which the Apple Event Manager provides coercion. The first column shows the descriptor type of the data to be coerced, and the second column shows the descriptor types that the Apple Event Manager can coerce it to.
  4516. For many Apple Event Manager functions, the Apple Event Manager attempts to coerce data to the descriptor type you specify even if the result is no longer meaningful. To ensure that no coercion is performed and that the descriptor type of the result is of the same descriptor type as the original, specify typeWildCard for the desired type.<36pt\>\x12 <8bat\>u
  4517. Coercion handling provided by the Apple Event Manager
  4518.     Original    Desired
  4519.     descriptor type    descriptor type    Description
  4520.     typeChar    typeLongInteger    Any string that is a valid 
  4521.         typeShortInteger    representation of a number 
  4522.         typeLongFloat    can be coerced into an 
  4523.         typeShortFloat    equivalent numeric value.
  4524.         typeExtended
  4525.         typeComp
  4526.         typeMagnitude
  4527.     typeLongInteger     typeChar    Any numeric descriptor type
  4528.     typeShortInteger        can be coerced into
  4529.     typeLongFloat        the equivalent text string.
  4530.     typeShortFloat
  4531.     typeExtended
  4532.     typeComp
  4533.     typeMagnitude
  4534.             Any numeric descriptor type
  4535.     typeLongInteger     typeLongInteger    can be coerced into any other
  4536.     typeShortInteger     typeShortInteger    numeric descriptor type.
  4537.     typeLongFloat     typeLongFloat
  4538.     typeShortFloat     typeShortFloat
  4539.     typeExtended     typeExtended
  4540.     typeComp    typeComp 
  4541.     typeMagnitude    typeMagnitude
  4542.     typeTrue    typeBoolean    The result is the Boolean value 
  4543.             TRUE.
  4544.     typeFalse    typeBoolean    The result is the Boolean value 
  4545.             FALSE.
  4546.     typeEnumerated    typeBoolean    The enumerated value 'true' 
  4547.             becomes the Boolean value 
  4548.             TRUE. The enumerated value 
  4549.             'fals' becomes the Boolean 
  4550.             value FALSE.
  4551.     typeBoolean    typeEnumerated    The Boolean value FALSE 
  4552.             becomes the enumerated value 
  4553.             'fals'. The Boolean value 
  4554.             TRUE becomes the enumerated 
  4555.             value 'true'.
  4556.     typeShortInteger    typeBoolean    A value of 1 becomes the 
  4557.             Boolean value TRUE. A value 
  4558.             of 0 becomes the Boolean 
  4559.             value FALSE.
  4560.     typeBoolean    typeShortInteger    A value of FALSE becomes 0.
  4561.             A value of TRUE becomes 1.
  4562. continued
  4563. Table 2-1    Coercion handling provided by the Apple Event Manager (continued)
  4564.     Original    Desired
  4565.     descriptor type    descriptor type    Description
  4566.     typeAlias    typeFSS    An alias record is coerced into a 
  4567.             file system specification record.
  4568.     typeAppleEvent    typeAppParameters    An Apple event is coerced into a 
  4569.             list of application parameters for 
  4570.             the LaunchParamBlockRec 
  4571.             parameter block.
  4572.     any descriptor type    typeAEList    A descriptor record is coerced 
  4573.             into a descriptor list containing a 
  4574.             single item.
  4575.     typeAEList    type of list item    A descriptor list containing a 
  4576.             single descriptor record is 
  4577.             coerced into a descriptor record.
  4578. Writing Object Accessor Functions
  4579. Most of the Apple events in the Core suite and the functional-area suites defined in the Apple Event Registry: Standard Suites can include parameters that consist of object specifier records. If the direct parameter for an Apple event consists of an object specifier record, your handler for the event should call the AEResolve function to resolve the object specifier record: that is, to find the Apple event objects it describes and, if necessary, their properties. The AEResolve function resolves object specifier records with the help of object accessor functions provided by your application. For an overview of the way AEResolve works with object accessor functions, see “Resolving Object Specifier Records,” which begins on page 2-53. 
  4580. This section describes how write object accessor functions. You need to read this section only if your application supports the Core suite or any of the functional area suites in the Apple Event Registry: Standard Suites.
  4581. Your application should provide object accessor functions that can find Apple event objects and their properties for all object classes supported by your application, including their corresponding properties and element classes. Since the Apple Event Manager dispatches object accessor functions according to the class ID of the requested Apple event object and the descriptor type of the token that identifies its container, you have a great deal of flexibility in deciding what object accessor functions you need to write for your application. The installation and dispatching of object accessor functions is described in “Installing Entries in the Object Accessor Dispatch Tables,” which begins on page 2-66.
  4582. For example, if your application is a word processor, one object accessor function will probably work equally well for Apple event objects of object classes cParagraph, cItem, and cWord located in containers identified by tokens of descriptor type myTextToken. If you use a single descriptor type for tokens that identify any containers in which Apple event objects of these three object classes can be found, you can dispatch requests for all such elements to the same object accessor function. However, the same word processor might use one descriptor type for tokens identifying containers of class cCell and another descriptor type for tokens identifying containers of class cColumn—in which case it would need an object accessor function for each descriptor type.
  4583. For each object class that your application supports, your application should also provide one object accessor function that can find all the properties of that object class, or one object accessor function that can find all the properties of several object classes.
  4584. Here’s the declaration for a sample object accessor function:
  4585. FUNCTION MyObjectAccessor (desiredClass: DescType; 
  4586.                                     containerToken: AEDesc; 
  4587.                                     containerClass: DescType;
  4588.                                     keyForm: DescType; keyData: AEDesc;
  4589.                                     VAR theToken: AEDesc; 
  4590.                                     theRefCon: LongInt): OSErr;
  4591. When the AEResolve function calls your object accessor function, it passes your function the object class ID of the requested Apple event objects, the object class of their container, a token that identifies the specific container in which to look for them, the key form and key data that specify how to locate them, and the reference constant associated with the object accessor function. Your object accessor function uses this information to locate the requested Apple event objects. 
  4592. A simple object specifier record always identifies either a single property (by property ID) or a single element in a container (by name or by absolute position). Therefore, if your application supports only simple object specifier records, the object accessor functions it provides need to support only the formPropertyID, formName, and formAbsolutePosition key forms.
  4593. A complex object specifier record can specify any number of Apple event objects using relative positions, tests, or ranges. If your application supports complex object specifier records, the object accessor functions it provides should support the key forms formRelativePosition, formRange, and formTest as well as the key forms used with simple object specifier records. In addition, you can optionally provide support for the key form formWhose. “Supporting Whose Descriptor Records” on page 2-170 explains how the key form formWhose can simplify the resolution of object specifier records for elements that belong to a larger group of elements that pass a test.
  4594. If your object accessor function successfully locates the requested Apple event objects, your application should return the noErr result code and a token that identifies the requested Apple event objects. The token can be of any descriptor type, as long as it is a descriptor record. For example, to identify a file, your application might use a descriptor record with the descriptor type typeAlias or typeFSS. To identify an open document, your application might define its own descriptor type, such as typeMyDocToken, that contains a handle to a document record.
  4595. If your object accessor function does not find the desired Apple event object, it should return the result code errAEEeventNotHandled as its function result, if no other error occurred.
  4596. Object accessor functions must not have side effects that change the number or order of elements in a container while an object specifier record is being resolved. If the number of elements in a container is changed during the resolution of an object specifier record, the Apple Event Manager may not be able to locate all the elements.<36pt\>\x12 <8bat\>s
  4597. Writing Object Accessor Functions That Find Apple Event Objects
  4598. The first three listings in this section demonstrate how to write three object accessor functions that might be called in the following situation: An application receives a Get Data event with a direct parameter that consists of an object specifier record for the first word in the third paragraph of a document. The application’s handler for the Get Data event calls the AEResolve function to resolve the object specifier record. The AEResolve function first calls the application’s object accessor function for Apple event objects of object class of cDocument in containers identified by a token of descriptor type of typeNull. 
  4599. The AEResolve function passes these parameters to the MyFindDocumentObjectAccessor function shown in Listing 2-35: the constant cDocument in the desiredClass parameter; the constant typeNull in the containerClass parameter; a descriptor record with a descriptor type of type typeNull and a NIL data handle in the containerToken parameter; the constant formName in the keyForm parameter; a descriptor record with a descriptor type of typeText and data that consists of the string "MyDoc" in the keyData parameter; and the reference constant specified in the application’s object accessor dispatch table.
  4600. Listing 2-33    An object accessor function that locates Apple event objects of object class cDocument by name
  4601. FUNCTION MyFindDocumentObjectAccessor 
  4602.                                         (desiredClass: DescType; 
  4603.                                         containerClass: DescType;
  4604.                                         containerToken: AEDesc; 
  4605.                                         keyForm: DescType; keyData: AEDesc;
  4606.                                         VAR token: AEDesc; 
  4607.                                         theRefCon: LongInt): OSErr;
  4608. VAR
  4609.     docName:                    Str255;
  4610.     actSize:                    Size;
  4611.     foundDoc:                    Boolean;
  4612.     foundDocRec:                    myDocumentRecord;
  4613. BEGIN
  4614.     IF keyForm = formName THEN
  4615.     BEGIN
  4616.         MyFindDocumentObjectAccessor := noErr;
  4617.         {get the name of the document from the key data}
  4618.         MyGetStringFromDesc(keyData, docName, actSize);
  4619.         IF actSize > 255 THEN
  4620.             DoError(gSizeTooBig);
  4621.         {Look for a document with the given name by }
  4622.         { searching all document records}
  4623.         foundDoc := MySearchDocRecs(docName, foundDocRec);
  4624.         IF foundDoc = FALSE THEN
  4625.             MyFindDocumentObjectAccessor = gObjectNotFound
  4626.         ELSE     {create token that identifies the document}
  4627.             MyFindDocumentObjectAccessor := 
  4628.                     AECreateDesc(typeMyDocToken, @foundDocRec,
  4629.                                         SizeOf(foundDocRec), token);
  4630.     END
  4631.     {handle the other key forms you support}
  4632.     ELSE
  4633.         MyFindDocumentObjectAccessor := kKeyFormNotSupported
  4634. END;
  4635. The MyFindDocumentObjectAccessor function uses the information in the keyForm and keyData parameters to find the specified document. If the MyFindDocumentObjectAccessor function finds the Apple event object, it returns a token with the application-defined descriptor type typeMyDocToken that identifies the document. The application defines the typeMyDocToken descriptor type as a descriptor record that contains a handle to a document record. The MyFindDocumentObjectAccessor function returns this token and the noErr result code to the AEResolve function.
  4636. In the Get Data example, the token returned to AEResolve by the MyFindDocumentObjectAccessor function identifies the document “MyDoc.” The AEResolve function then calls the application’s object accessor function for Apple event objects of object class cParagraph in containers identified by a token of descriptor type of typeMyDocToken. 
  4637. In this case, the AEResolve function passes these parameters to the MyFindParaObjectAccessor function shown in Listing 2-34: the constant cParagraph in the desiredClass parameter; the constant cDocument in the containerClass parameter; the token returned by the MyFindDocumentObjectAccessor function (a descriptor record with the typeMyDocToken descriptor type and handle to a document record) in the containerToken parameter; the constant formAbsolutePosition in the keyForm parameter; a descriptor record with the typeLongInteger descriptor type and data that consists of the value 3 (indicating the third paragraph) in the keyData parameter; and the reference constant specified in the application’s object accessor dispatch table.
  4638. Listing 2-34    An object accessor function that locates Apple event objects of object class cParagraph
  4639. FUNCTION MyFindParaObjectAccessor (desiredClass: DescType; 
  4640.                                                 containerClass: DescType;
  4641.                                                 containerToken:    AEDesc; 
  4642.                                                 keyForm: DescType; keyData: 
  4643.                                                 AEDesc; VAR token: AEDesc; 
  4644.                                                 theRefCon: LongInt): OSErr;
  4645. VAR
  4646.     paraNumber:                    LongInt;
  4647.     {myFoundTextRecord is an application-defined data type, } 
  4648.     { consisting of two fields (paraStart and paraEnd)} 
  4649.     foundParaRec:                    myFoundTextRecord;
  4650.     foundParaStart:LongInt;
  4651.     foundParaEnd:                    LongInt;
  4652. BEGIN
  4653.     IF keyForm = formAbsolutePosition THEN
  4654.     BEGIN
  4655.         {get the index of the paragraph from the key data}
  4656.         MyGetIndexFromDesc(keyData, index);
  4657.         {Get the desired paragraph by index}
  4658.         MyGetPara(index, containerToken, foundParaStart, 
  4659.                         foundParaEnd);
  4660.         IF foundParaStart = 0 THEN
  4661.             MyFindParaObjectAccessor := gObjectNotFound
  4662.         ELSE     {create token that identifies the paragraph}
  4663.             BEGIN
  4664.             foundParaRec.paraStart := foundParaStart;
  4665.             foundParaRec.paraEnd := foundParaEnd;
  4666.             MyFindParaObjectAccessor := 
  4667.                     AECreateDesc(typeMyParaToken, @foundParaRec,
  4668.                                         SizeOf(foundParaRec), token);
  4669.         END;
  4670.     END
  4671.     {handle the other key forms you support}
  4672.     ELSE 
  4673.         MyFindParaObjectAccessor := kKeyFormNotSupported
  4674. END;
  4675. The MyFindParaObjectAccessor function uses another application-defined function, MyGetPara, to search the data structures associated with the document and find the desired paragraph. (The document is specified by the containerToken parameter.) If the MyGetPara function finds the Apple event object, it returns a pointer to the beginning of the paragraph and a pointer to the end of the paragraph. The MyFindParaObjectAccessor function returns a token with the application-defined descriptor type typeMyParaToken that identifies the requested paragraph. The application defines the typeMyParaToken descriptor type as a descriptor record that contains pointers to the beginning and ending locations of the paragraph. The MyFindParaObjectAccessor function returns this token and the noErr result code to the AEResolve function.
  4676. In the Get Data example, the token returned to AEResolve by the MyFindParaObjectAccessor function identifies the third paragraph in the document “MyDoc.” The AEResolve function then calls the application’s object accessor function for Apple event objects of object class cWord in containers identified by a token of descriptor type typeMyParaToken. 
  4677. In this case, the AEResolve function passes these parameters to the MyFindWordObjectAccessor function shown in Listing 2-35: the constant cWord as the desiredClass parameter; the constant cParagraph as the containerClass parameter; the token returned by the MyFindParagraphObjectAccessor function (a descriptor record with the typeMyParaToken descriptor type and handle to a paragraph record) in the container parameter; the constant formAbsolutePosition in the keyForm parameter; a descriptor record with the typeLongInteger descriptor type and data that consists of the value 1 (indicating the first word) in the keyData parameter; and the reference constant specified in the application’s object accessor dispatch table.
  4678. The MyFindWordObjectAccessor function uses another application-defined function, MyGetWord, to search the paragraph to find the desired word. (The paragraph is specified by the containerToken parameter.) If the MyGetWord function finds the Apple event object, it returns a pointer to the beginning of the word and a pointer to the end of the word (or it could return a string). The MyFindWordObjectAccessor function then creates a token with the application-defined descriptor type typeMyWordToken that identifies the requested word. The application defines the typeMyWordToken descriptor type as a descriptor record that contains in its data field pointers to the beginning and ending locations of the word (or it could be defined as a string). The MyFindWordObjectAccessor function returns this token and the noErr result code to the AEResolve function, which in turn returns the token to the application’s handler for the Get Data event that originally called AEResolve.
  4679. Listing 2-35    An object accessor function that locates Apple event objects of object class cWord
  4680. FUNCTION MyFindWordObjectAccessor 
  4681.                                         (desiredClass: DescType; 
  4682.                                         containerType: DescType;
  4683.                                         containerToken: AEDesc; 
  4684.                                         keyForm: DescType; keyData: AEDesc;
  4685.                                         VAR token: AEDesc; 
  4686.                                         theRefCon: LongInt): OSErr;
  4687. VAR
  4688.     wordNumber:                    LongInt;
  4689.     foundWordRec:                    myFoundTextRecord;
  4690.     foundWordStart:    LongInt;
  4691.     foundWordEnd:                    LongInt;
  4692. BEGIN
  4693.     IF keyForm = formAbsolutePosition THEN
  4694.     BEGIN
  4695.         {get the index of the word from the key data}
  4696.         MyGetIndexFromDesc(keyData, index);
  4697.         {Get the desired word by index}
  4698.         MyGetWord(index, containerToken, foundWordStart, 
  4699.                         foundWordEnd);
  4700.         IF foundWordStart = 0 THEN
  4701.             MyFindWordObjectAccessor := gObjectNotFound
  4702.         ELSE     {create token that identifies the paragraph}
  4703.             BEGIN
  4704.             foundWordRec.start := foundWordStart;
  4705.             foundWordRec.end := foundWordEnd;
  4706.             MyFindWordObjectAccessor := 
  4707.                     AECreateDesc(typeMyWordToken, @foundWordRec,
  4708.                                         SizeOf(foundWordRec), token);
  4709.             END;
  4710.     END
  4711.     {handle the other key forms you support}
  4712.     ELSE 
  4713.         MyFindWordObjectAccessor := kKeyFormNotSupported
  4714. END;
  4715. Listing 2-33 shows an object accessor function that locates a document in the default container. Every application must provide one or more object accessor functions that can find Apple event objects in the default container, which is always identified by a descriptor record of descriptor type typeNull. Listing 2-36 provides another example of an object accessor function that locates an Apple event object in the default container. If the MyFindWindowObjectAccessor function shown in Listing 2-36 were installed in an application’s object accessor dispatch table, the AEResolve function would call it whenever AEResolve needed to locate an Apple event object of the object class cWindow in a container identified by a token of descriptor type typeNull.
  4716. Listing 2-36    An object accessor function that locates Apple event objects of the object class cWindow
  4717. FUNCTION MyFindWindowObjectAccessor (desiredClass: DescType; 
  4718.                                         containerClass: DescType;
  4719.                                         containerToken: AEDesc; 
  4720.                                         keyForm: DescType; keyData: AEDesc;
  4721.                                         VAR token: AEDesc; 
  4722.                                         theRefCon: LongInt): OSErr;
  4723. VAR
  4724.     windowName:                    Str255;
  4725.     actSize:                    Size;
  4726.     windTitle:                    Str255;
  4727.     window:                    WindowPtr;
  4728.     index:                    Integer;
  4729.     iLoop:                    Integer;
  4730.     found:                    Boolean;
  4731. BEGIN
  4732.     IF keyForm = formName THEN
  4733.     BEGIN
  4734.         {get the name of the window to find from the keyData }
  4735.         { parameter. MyGetStringFromDesc gets data out of an }
  4736.         { AEDesc and returns a string and the string’s size}
  4737.         MyGetStringFromDesc(keyData, windowName, actSize);
  4738.         IF actSize > 255 THEN
  4739.             DoError(gSizeTooBig);
  4740.         {Look for a window with the given name}
  4741.         window := FrontWindow;
  4742.         found := FALSE;
  4743.         WHILE (window <> NIL) AND (found <> TRUE) DO 
  4744.         BEGIN
  4745.             GetWTitle(window, windTitle);
  4746.             IF EqualString(windTitle, windowName, FALSE, TRUE) 
  4747.                                 THEN
  4748.                 found := TRUE;                        {found it!}
  4749.             IF (found = FALSE) THEN
  4750.                 window := 
  4751.                         WindowPtr(WindowPeek(window)^.nextWindow);
  4752.         END;             {of while}
  4753.         IF window = NIL THEN
  4754.             MyFindWindowObjectAccessor := gObjectNotFound
  4755.         ELSE     {create token that identifies the window}
  4756.         MyFindWindowObjectAccessor := AECreateDesc 
  4757.                     (typeMyWindow, @window, SizeOf(window), token);
  4758.     END; {of formName}
  4759.  
  4760.     IF keyForm = formAbsolutePosition THEN
  4761.         {find the window given an index in key data}    
  4762.         BEGIN            {get the index from the key data}                    
  4763.             MyGetIndexFromDesc(keyData, index);
  4764.             iLoop := 0;
  4765.             window := FrontWindow;
  4766.             WHILE (window <> NIL) AND (found <> TRUE) DO
  4767.             BEGIN
  4768.                 iLoop := iLoop +1;
  4769.                 IF iLoop = index THEN
  4770.                     found := TRUE
  4771.                 ELSE
  4772.                 window := 
  4773.                 WindowPtr(WindowPeek(window)^.nextWindow);
  4774.             END; {of while}
  4775.             IF window = NIL THEN
  4776.                 MyFindWindowObjectAccessor := gObjectNotFound
  4777.             ELSE     {create token that identifies the window}
  4778.                 MyFindWindowObjectAccessor := 
  4779.                             AECreateDesc(typeMyWindow, @window, 
  4780.                                                 SizeOf(window), token);
  4781.     END        {of formAbsolutePosition}
  4782.     {handle the other key forms you support}
  4783.     ELSE 
  4784.         MyFindWordObjectAccessor := kKeyFormNotSupported
  4785. END;
  4786. The keyForm parameter of the MyWindowObjectAccessor function describes how the function should interpret the keyData parameter. If the key form is formName, then the key data contains the name of the window to locate. If the key form is formAbsolutePostion, the key data contains the position of the window in the window list to locate; for example, key data of 1 identifies the frontmost window.
  4787. The MyWindowObjectAccessor function only supports the formName and formAbsolutePosition key words. Your object accessor functions should support all key forms that make sense for the object classes whose Apple event objects it can locate.
  4788. For the formName key word, the MyWindowObjectAccessor function starts with the frontmost window and compares the window’s title to the name specified by the keyData parameter. It continues this search until either the end of the window list is reached or a match is found. If the MyWindowObjectAccessor function finds a match, it uses the AECreateDesc function to create a descriptor record for the token, specifying the application-defined typeMyWindow descriptor type and the data for this descriptor type as a window pointer. 
  4789. The MyWindowObjectAccessor function then sets its function result appropriately, and the AEResolve function either returns this function result and token, or uses the returned token to request the next Apple event object in the container hierarchy, such as a document in the window. 
  4790. Writing Object Accessor Functions That Find Properties
  4791. The Apple event object to which a property belongs is that property’s container. Your application should provide an object accessor function for finding properties in containers identified by tokens of various descriptor types. Your application does not need to be given a property’s specific object class in order to find that property; instead, you can specify the object class ID for any property with the constant cProperty. This means you can write a single object accessor function that can find any property of a container identified by a token of a given descriptor type. 
  4792. To specify such an object accessor function, you can add a single entry to the object accessor dispatch table that specifies the desired object class as cProperty for a given token descriptor type. For example, Listing 2-37 shows an object accessor function that finds any property of any Apple event object identified by a token of type typeMyWindowProp.
  4793. Listing 2-37    An object accessor function that finds any property of an Apple event object identified by a token of descriptor type typeMyWindow
  4794. FUNCTION MyFindPropertyOfWindowObjectAccessor 
  4795.                                         (desiredClass: DescType; 
  4796.                                         containerType: DescType;
  4797.                                         containerToken:    AEDesc; 
  4798.                                         keyForm: DescType; keyData: AEDesc;
  4799.                                         VAR theToken: AEDesc; 
  4800.                                         theRefCon: LongInt): OSErr;
  4801. VAR
  4802.     theWindow:                 WindowPtr;
  4803. BEGIN
  4804.     MyFindPropertyOfWindowObjectAccessor := noErr;
  4805.     IF keyForm = formPropertyID THEN
  4806.     BEGIN
  4807.         IF keyData.descriptorType = pName THEN
  4808.         BEGIN
  4809.             MyGetTokenData (theWindow, containerToken);
  4810.             MyCreateToken(typeMyWindowProp, theWindow, theToken);
  4811.         END; {of pName}
  4812.         IF keyData.descriptorType = pBounds THEN
  4813.         BEGIN
  4814.             MyGetTokenData (theWindow, containerToken);
  4815.             MyCreateToken(typeMyWindowProp, theWindow, pBounds, 
  4816.                                 theToken);
  4817.         END; {of pBounds}
  4818.  
  4819. {find other properties as appropriate}
  4820.  
  4821.     ELSE
  4822.         MyFindPropertyOfWindowObjectAccessor := 
  4823.                                                         errorAEPropNotFound;
  4824. END; 
  4825. Defining Tokens 
  4826. It is up to you to decide how many token descriptor types you need to define for your application. In many cases you may be able to define one token that can identify Apple event objects of several different object classes, such as a typeMyText token that identifies Apple event objects of object classes cText, cWord, cItem, and cChar. In other cases you may need to define specific token descriptor types for specific object classes.
  4827. For example, the MyFindDocumentObjectAccessor routine shown in Listing 2-33 on page 2-160 returns a token of descriptor type typeMyDocToken, which contains a document record:
  4828. CONST                                             {application-defined token}
  4829.     typeMyDocToken                            = 'docr';             {a document record}
  4830. Descriptor record for an application-defined token that identifies a document
  4831. The MyFindPropertyOfWindowObjectAccessor routine shown in Listing 2-37 returns a token of descriptor type typeMyWindowProp for every property that it can locate: 
  4832. CONST                                             {application-defined token}
  4833.     typeMyWindowProp                            = 'wprp';             {a window pointer and a }
  4834.                                              { property ID}
  4835. Descriptor record for an application-defined token that identifies a property
  4836. When an object accessor function that supports key form formRange locates a range of Apple event objects, it should normally return a descriptor list (AEDescList) of tokens for the individual objects. However, an object accessor function that returns a range of text should usually return a single token representing the whole range; for example, it makes more sense to return a single token that identifies a range of text from character 3 to character 17 rather than a group of tokens that each represent one character. 
  4837. A token is valid only until the Apple Event Manager has located the requested element in the container the token represents and returned another token for the element. The Apple Event Manager disposes of tokens it obtains while resolving an object specifier record, but one token is always left over—the token that identifies the specified Apple event object or objects. Your application should dispose of this final token by calling the AEDisposeToken function, which in turn calls your application’s token disposal function (if it has one), an optional object callback function that disposes of a token. A declaration for a token disposal function is described on page 2-260. 
  4838. If your application does not provide a token disposal function, the Apple Event Manager uses the AEDisposeDesc function to dispose of a descriptor record. For some applications, disposing of tokens may involve more than simply disposing of a descriptor record, and may therefore require a custom token disposal function. For example, the data field of a token descriptor record might contain a handle to a block that in turn contains references to storage for the Apple event object referred to by the token. These applications can provide a token disposal function that performs the additional tasks that are necessary. 
  4839. Supporting Whose Descriptor Records
  4840. An object specifier record with the key form formWhose is never created directly by an application. Instead, the Apple Event Manager collapses the key form and key data from two object specifier records in a container hierarchy into one object specifier record with the key form formWhose and key data that consists of a whose descriptor record, a descriptor record of descriptor type typeWhoseDescriptor. The target application can often locate Apple event objecst more efficiently with a whose descriptor record than would otherwise be possible. For example, Figure 2-24 on page 2-137 shows four object specifier records that specify the container hierarchy for the first row in the table “MyAddresses” of the database “GigaBase” that meets a test. A server application might be able to locate the requested row more quickly if it could simply test each table until it finds the first one that passes the test, rather than identifying all the tables that pass the test and then locating the first one in that group. 
  4841. Support for whose descriptor records is optional, and is useful only for applications that can make use of a test combined with either an absolute position or a range to locate Apple event objects. If you want the Apple Event Manager to pass your application object specifier records of type formWhose whenever possible, you must set the kAEIDoWhose flag in the callBackFlags parameter of the AEResolve function. If for any reason your application cannot handle a particular whose descriptor record, it should return errAEEventNotHandled as the result code, and the Apple Event Manager will try again using the original object specifier records.
  4842. If a server application that supports whose descriptor records receives an object specifier record with the container hierarchy shown in Figure 2-24, the Apple Event Manager will automatically collapse the four nested object specifier records into three, as shown in Figure 2-28.
  4843. A container hierarchy created by the Apple Event Manager for a server application that supports whose descriptor records
  4844. A whose descriptor record is a coerced AE record that consists of two keyword-specified descriptor records with the following keywords:
  4845. Keyword        Description
  4846. keyAEIndex        A descriptor record of either type typeLongInteger or type typeAbsoluteOrdinal specifying an absolute position among those Apple event objects that pass the test; or a descriptor record of type typeWhoseRange specifying a range of Apple event objects that pass the test.  
  4847. keyAETest        A descriptor record of either type typeCompDescriptor or type typeLogicalDescriptor that specifies a test. 
  4848. If the Apple Event Manager encounters a range descriptor record that specifies a range of Apple event objects that pass a test, it will, under certain conditions, coerce the range descriptor record to a whose range descriptor record. A whose range descriptor record is a coerced AE record of typeWhoseRange that consists of two keyword-specified descriptor records with the following keywords:
  4849. Keyword        Description
  4850. keyAEWhoseRangeStart        A descriptor record of either type typeLongInteger or type typeAbsoluteOrdinal specifying the absolute position of the Apple event object, within the set of all elements that pass a test, that identifies the beginning of the desired range. 
  4851. keyAEWhoseRangeStop        A descriptor record of either type typeLongInteger or type typeAbsoluteOrdinal specifying the absolute position of the Apple event object, within the set of all elements that pass a test, that identifies the end of the desired range.
  4852. When resolving an object specifier record for a target application that supports formWhose, the Apple Event Manager will coerce a range descriptor record to a whose range descriptor record if the container for the specified range of Apple event objects is a group of Apple event objects that pass a test, and if the boundary objects in the original range descriptor record meet three conditions: 
  4853. n    Both boundary objects are of the same object class as the Apple event objects in the range they specify.
  4854. n    The object specifier record for each boundary object specifies its container with a descriptor record of descriptor type typeCurrentContainer.
  4855. n    The object specifier record for each boundary object specifies a key form of formAbsolutePosition.
  4856. When your application receives a request for an Apple event object identified by a key form of formWhose, the appropriate object accessor function in your application must coerce the whose descriptor record specified as the key data to an AE record and extract the data from the AE record using the AEGetKeyPtr and AEGetKeyDesc routines. If the keyword-specified descriptor record with the keyword keyAEIndex consists of a descriptor record of descriptor type typeWhoseRange, your object accessor function must also coerce that descriptor record to an AE record and extract the data. Your object accessor function should then attempt to locate the requested Apple event objects and, if successful, return a token that identifies them.  
  4857. Writing Object Callback Functions
  4858. If an Apple event parameter consists of an object specifier record, your handler for the Apple event typically calls AEResolve to begin the process of locating the requested Apple event object or objects. AEResolve in turn calls object accessor functions and, if necessary, object callback functions provided by your application.
  4859. Every application that supports Apple event objects should provide object accessor functions that can locate Apple event objects belonging to any of the supported object classes. For an overview of the way AEResolve calls object accessor functions in order to locate Apple event objects described by object specifier records, see “Resolving Object Specifier Records,” which begins on page 2-53.
  4860. In addition to object accessor functions, your application can provide up to seven object callback functions:
  4861. n    An object-counting function counts the number of elements of a specified class in a specified container, so that the Apple Event Manager can determine how many elements it must examine to find the element or elements that pass a test. Your application must provide one object-counting function if it supports complex object specifier records.  For information on writing an object-counting function, see “Writing an Object-Counting Function,” which begins on page 2-175.
  4862. n    An object comparison function compares one element to either another element or to a descriptor record and returns either TRUE or FALSE. Your application must provide one object comparison function if it supports complex object specifier records. For information on writing an object comparison function, see “Writing an Object Comparison Function,” which begins on page 2-177.
  4863. n    A token disposal function disposes of a token after your application calls the AEDisposeToken function. If your application doesn’t provide a token disposal function, the Apple Event Manager uses the AEDisposeDesc function instead. Your application must provide one token disposal function if it supports object marking or if it requires more than a call to AEDisposeDesc to dispose of one of its tokens. The declaration for a token disposal function is described on page 2-260.
  4864. n    An error callback function gives the Apple Event Manager an address to which to write the descriptor record it is currently working with if an error occurs while AEResolve is attempting to resolve an object specifier record. Your application is not required to provide an error callback function. The declaration for an error callback function is described on page 2-260.
  4865. n    Three marking callback functions are used by the Apple Event Manager to get a mark token from your application, to mark specific Apple event objects, and to adjust the marks on a group of marked Apple event objects. Your application must provide all three marking functions if it supports marking.  For information on writing marking functions, see “Writing Marking Callback Functions,” which begins on page 2-179.
  4866. To make your object callback functions available to the Apple Event Manager, use the AESetObjectCallbacks function: 
  4867. myErr := AESetObjectCallbacks (myCompareProc, myCountProc, 
  4868.                                          myDisposeTokenProc, 
  4869.                                          myGetMarkTokenProc, myMarkProc, 
  4870.                                          myAdjustMarksProc, 
  4871.                                          myGetErrDescProc);
  4872. Each parameter to the AESetObjectCallbacks function consists of either a pointer to the corresponding application-defined function or NIL if no function is provided. AESetObjectCallbacks sets object callback functions that are available only to your application. To set system object callback functions, which are available to all applications and processes running on the same computer, use the AEInstallSpecialHandler function as described on page 2-251.
  4873. If your application supports complex object specifier records, it should provide an object-counting function and an object comparison function. The Apple Event Manager calls your application’s object-counting function in order to determine the number of Apple event objects in a specified container that need to be tested. The Apple Event Manager calls your application’s object comparison function when it needs to compare one Apple event object to either another Apple event object or to a value in a descriptor record.
  4874. If your application does not provide a token disposal function, the Apple Event Manager uses the AEDisposeDesc function to dispose of a token. But for some applications, disposing of tokens may involve more than simply disposing of a descriptor record, and may therefore require a custom token disposal function. For example, the data field of a token descriptor record might contain a handle to a block that in turn contains references to storage for the Apple event object referred to by the token. These applications can provide a token disposal function that performs the additional tasks that are necessary. 
  4875. Whenever more than one Apple event object passes a test, AEResolve can either return a list of tokens or make use of a target application’s ability to mark its own objects. Sometimes a list of tokens can become unmanageably large. For example, if a Get Data event asks for the names and addresses of all customers with a specified zip code who have purchased a specified product, the object accessor function that locates all the customers with the specified zip code might return a list of many thousands of tokens; the elements identified by those tokens would then have to be tested for the specified product. However, if your application uses some method of marking objects, you can choose simply to mark the requested objects rather than returning a list of tokens. “Writing Marking Callback Functions” on page 2-179 describes how to do this. If you provide marking functions, you must also provide a token disposal function. 
  4876. When one of your application’s Apple event handlers calls the AEResolve function, the handler should pass a value in the second parameter that specifies whether your application supports whose descriptor records or provides marking callback functions. You can add the following constants, as appropriate, to provide a value for the second parameter: 
  4877. CONST kAEIDoMinimum                            =    $0000 ; {Does not provide callbacks}
  4878.         kAEIDoWhose                    =    $0001 ; {Supports key form formWhose}
  4879.         kAEIDoMarking                    =    $0004 ; {Provides marking functions}
  4880. For example, this code instructs the Apple Event Manager to call any marking functions previously set with the AESetObjectCallbacks function while resolving the object specifier record in the objectSpecifier parameter:
  4881. VAR
  4882.     objectSpecifier:    AEDesc;
  4883.     resultToken:        AEDesc;
  4884.     myErr:              OSErr;
  4885.  
  4886. myErr := AEResolve(objectSpecifier, kAEIDoMarking, resultToken); 
  4887. Writing an Object-Counting Function
  4888. If your application supports Apple event objects that can contain more than one element, you must provide an object-counting function. Your object-counting function should be able to count the number of elements of a given object class in a given container. For example, if your application supports Apple event objects that belong to the object class cText in the Text suite, your application should provide an object-counting function that can count Apple event objects of each element class listed in the definition of cText in the Apple Event Registry: Standard Suites. In this case, your application should provide an object-counting function that can count the number of words, items, or characters in a text object.
  4889. You specify your object-counting function with the AESetObjectCallbacks function. Once you set your object-counting function, the Apple Event Manager calls your object-counting function whenever it is resolving an object specifier record and it requires a count of the number of elements in a given container.
  4890. Here’s the declaration for a sample object-counting function:
  4891. FUNCTION MyCountObjects (desiredClass: DescType; 
  4892.                                  containerClass: DescType;
  4893.                                  containerToken: AEDesc; 
  4894.                                  VAR result: LongInt): OSErr;
  4895. When the Apple Event Manager calls your object-counting function, it passes the object class ID of the Apple event objects to count, the object class of their container, and a token identifying their container. (The container class can be useful if you want to use one token type for several object classes.) Your object-counting function uses this information to count the number of Apple event objects of the specified object class in the specified container. After counting the Apple event objects, your application should return the noErr result code and should also return the number of Apple event objects counted in the result parameter. 
  4896. Listing 2-38 shows an application-defined function, MyCountObjects, that counts the number of objects for any object class supported by the application. 
  4897. An object-counting function
  4898. FUNCTION MyCountObjects (desiredClass: DescType; 
  4899.                                   containerClass: DescType; containerToken: AEDesc; 
  4900.                                   VAR result: LongInt): OSErr;
  4901. VAR
  4902.     myErr:          OSErr;
  4903.     window: WindowPtr;
  4904. BEGIN
  4905.     result := 0;
  4906.     IF desiredClass = cWindow THEN
  4907.     BEGIN
  4908.         IF containerClass = typeNull THEN
  4909.             BEGIN
  4910.             {count the number of windows}
  4911.             window := FrontWindow;
  4912.             WHILE (window <> NIL) DO 
  4913.                 BEGIN
  4914.                     result := result + 1;
  4915.                     window := WindowPtr(WindowPeek(window)^.nextWindow);
  4916.                 END; {of while}            
  4917.             END; 
  4918.         myErr := noErr;
  4919.     END; {of cWindow}
  4920.  
  4921.     IF desiredClass = cWord THEN
  4922.     BEGIN            {count the number of words in the container}                        
  4923.         myErr := MyCountWords(containerClass, containerToken, result);
  4924.     END;        {of cWord}
  4925.  
  4926.     IF desiredClass =     cParagraph THEN
  4927.     BEGIN        {count the number of paragraphs in the container}                        
  4928.         myErr := MyCountParas(containerClass, containerToken, result);
  4929.     END;        {of cParagraph}
  4930.  
  4931.     {this app does not support any other object classes}
  4932.     IF (desiredClass <> cWindow) AND (desiredClass <> cWord AND 
  4933.                                         (desiredClass <> cParagraph) THEN
  4934.     MyCountObjects := kObjectClassNotFound
  4935.     ELSE
  4936.     MyCountObjects := myErr;
  4937. END; 
  4938. Writing an Object Comparison Function
  4939. If your application supports complex object specifier records, you must provide an object comparison function. Your object comparison function should be able to compare one Apple event object to another Apple event object or to another descriptor record. For example, if your application supports the formTest key form, which can be used with the key data in an object specifier record to compare elements of a given container with a given Apple event object or the contents of a given descriptor record, your application should provide an object comparison function. 
  4940. You specify your object comparison function to the Apple Event Manager using the AESetObjectCallbacks function. Once you set your object comparison function, the Apple Event Manager calls your object comparison function whenever it is resolving Apple event objects and needs to test or compare the value of an Apple event object with another Apple event object or descriptor record.
  4941. Here’s the declaration for a sample object comparison function:
  4942. FUNCTION MyCompareObjects (comparisonOperator: DescType; 
  4943.                                     object: AEDesc;
  4944.                                     objectOrDescToCompare: AEDesc; 
  4945.                                     VAR result: Boolean): OSErr;
  4946. When the Apple Event Manager calls your object comparison function, it passes a comparison operator that specifies how the two objects should be compared, the object specifier record that describes the first Apple event object, and either an object specifier record that describes the Apple event object to compare or a descriptor record.
  4947. It is up to your application to interpret the comparison operators it receives. The meaning of comparison operators differs depending on the Apple event objects being compared, and not all comparison operators apply to all object classes. After successfully comparing the Apple event objects, your object comparison function should return the noErr result code and should also return a Boolean value in the result parameter, specifying TRUE if the result of the comparison is true, and FALSE otherwise. If for any reason your comparison function is unable to compare the specified Apple event objects, it should return the result code errAEEventNotHandled; then the Apple Event Manager will try an alternative method of comparing the Apple event objects, such as calling the equivalent system object comparison function, if one exists.
  4948. Your object comparison function should be able to compare an Apple event object belonging to any object class supported by your application with another Apple event object. Your object comparison function should also be able to compare two Apple event objects with different object classes if appropriate. For example, an object comparison function for a word processing application might be asked to compare the First Name column of a specified row in a table with the first word on a specified page—that is, to compare an Apple event object of object class cColumn with an Apple event object of object class cWord. You must decide what kinds of comparisons make sense for your applicatio.
  4949. The Apple Event Registry: Standard Suites defines standard comparison operators. Here is a list of the constants that correspond to these comparison operators: 
  4950. CONST
  4951.     kAEGreaterThan                            = '>=  ';         {the value of the first }
  4952.                                              { operand is greater than the }
  4953.                                              { value of the second operand}
  4954.     kAEGreaterThanEquals                            = '>   ';         {the value of the first }
  4955.                                              { operand is greater than or }
  4956.                                              { equal to the value of the }
  4957.                                              { second operand}
  4958.     kAEEquals                            = '=   ';         {the value of the first }
  4959.                                              { operand equals the value of }
  4960.                                              { the second operand}
  4961.     kAELessThan                            = '<   ';         {the value of the first }
  4962.                                              { operand is less than the }
  4963.                                              { value of the second operand}
  4964.     kAELessThanEquals                            = '<=  ';         {the value of the first }
  4965.                                              { operand is less than or }
  4966.                                              { equal to the value of the }
  4967.                                              { second operand}
  4968.     kAEBeginsWith                            = 'bgwt';         {the value of the first }
  4969.                                              { operand begins with the }
  4970.                                              { value of the second operand}
  4971.     kAEEndsWith                            = 'ends';        { the value of the first }
  4972.                                              { operand ends with the value }
  4973.                                              { of the second operand}
  4974.     kAEContains                            = 'cont';         {the value of the first }
  4975.                                              { operand contains the value }
  4976.                                              { of the second operand} 
  4977. Listing 2-39 shows an application-defined function, MyCompareObjects, that compares two Apple event objects of any object class supported by the application. 
  4978. Object comparison function that compares two Apple event objects
  4979. FUNCTION MyCompareObjects (comparisonOperator: DescType; 
  4980.                                     object: AEDesc;
  4981.                                     objectOrDescToCompare: AEDesc; 
  4982.                                     VAR result: Boolean): OSErr;
  4983. VAR
  4984.     myErr:                    OSErr;
  4985. BEGIN
  4986.     result := FALSE;
  4987.     IF comparisonOperator =                         kAEEquals THEN
  4988.     BEGIN            {compare two objects for equivalence}
  4989.         result := MyCompEquals(object, objectOrDescToCompare);
  4990.     END; {of kAEEquals}
  4991.  
  4992.     IF comparisonOperator =                         kAEGreaterThan THEN
  4993.     BEGIN            {compare two objects}
  4994.         result := MyCompGreaterThan(object, objectOrDescToCompare);
  4995.     END; {of kAEGreaterThan}
  4996.  
  4997.     IF comparisonOperator =                         kAELessThan THEN
  4998.     BEGIN            {compare two objects}
  4999.         result := MyCompLessThan(object, objectOrDescToCompare);
  5000.     END; {of kAELessThan}
  5001.  
  5002.     {this app does not support any other comparison operators}
  5003.  
  5004.     IF result = TRUE THEN
  5005.         MyCompareObjects := noErr
  5006.     ELSE
  5007.         MyCompareObjects := errAEEventNotHandled;
  5008. END;
  5009. The MyCompareObjects function calls a separate application-defined routine for each comparison operator. In each case, the application-defined routine that actually performs the comparison can compare an Apple event object with either another Apple event object or with a descriptor record’s data. If for any reason the comparison cannot be performed, the MyCompareObjects functions returns the result code errAEEventNotHandled. 
  5010. Writing Marking Callback Functions
  5011. Marking callback functions allow applications such as databases that can mark their own objects to take advantage of that capability when resolving object specifier records. Instead of returning a list of tokens for a group of Apple event objects that pass a test, your application can simply mark the Apple event objects and return a token that identifies how they have been marked. This can both speed up the resolution of complex object specifier records and reduce the amount of memory you need to allocate for tokens. 
  5012. The use of marking callback functions is optional, and only makes sense if you can reasonably expect that the tokens created in the process of resolving some object specifier records might not all fit in memory at once, and if your application already uses a marking mechanism. If you want the Apple Event Manager to use marking callback functions provided by your application, you must add the kAEIDoMarking constant to the value of the callBackFlags parameter for the AEResolve function. If for any reason your application cannot mark a requested set of Apple event objects, it should return eventNotHandled as the result code, and the Apple Event Manager will attempt to continue resolving the object specifier record by some other method, such as using a system marking function, if one exists, or using object accessor functions without calling marking callback functions. 
  5013. If your application supports marking callback functions, it must provide three functions with declarations modeled after these samples:
  5014. FUNCTION MyGetMarkToken (containerToken: AEDesc; 
  5015.                                  containerClass: DescType; 
  5016.                                  VAR Result: AEDesc): OSErr;
  5017. FUNCTION MyMark (theToken: AEDesc; markToken: AEDesc; 
  5018.                       markCount: LongInt): OSErr;
  5019. FUNCTION MyAdjustMarks (newStart,newStop: LongInt; 
  5020.                                 markToken: AEDesc): OSErr;
  5021. For more detailed information about these sample declarations, see “Object Callback Functions,” which begins on page 2-256.
  5022. To resolve a given object specifier record with the aid of the marking callback functions provided by your application, the Apple Event Manager first calls your application’s mark token function (MyGetMarkToken), passing a token that identifies the container of the elements to be marked in the containerToken parameter and the container’s object class in the containerClass parameter. The mark token function returns a mark token. A mark token, like other tokens, can be a descriptor record of any type; however, unlike other tokens, it identifies the way your application will mark Apple event objects during the current session while resolving a single test. A mark token does not identify a specific Apple event object; rather, it contains information for the use of your application that specifies how one or more Apple event objects are marked.
  5023. After it receives the mark token, the Apple Event Manager can call your application’s object-marking function (MyMark) repeatedly to mark specific Apple event objects. The Apple Event Manager passes the marking function a token for the object to be marked (obtained from the appropriate object accessor function) in the theToken parameter; the current mark token in the markToken parameter; and the mark count in the markCount parameter. The mark count indicates the number of times the Apple Event Manager has called the marking function for the current mark token. Your application should record the mark count at the time each Apple event object is marked. The mark count recorded for each marked Apple event object allows your application to distinguish one set of marked objects from another when a single object specifier record specifies more than one test.
  5024. When the Apple Event Manager needs to identify either a range of elements or the absolute position of an element in a group of Apple event objects that pass a test, it can use your applications’ mark-adjusting function (MyAdjustMarks) to unmark objects that it has previously marked with your marking function . For example, if an object specfier record specifies “any row in the table ‘My Customers’ for which the City column is ‘San Francisco’,” the Apple Event Manager first uses the appropriate object accessor routine to locate all the rows in the table for which the City column is “San Francisco,” and calls the application’s marking function repeatedly to mark them; it then generates a random number between 1 and the number of rows it found that passed the test, and calls the application’s mark-adjusting function to unmark all the rows whose mark count does not match the randomly generated number. If the randomly chosen row has a mark count value of 5, the Apple Event Manager passes the mark-adjusting function 5 in both the newStart parameter and the newStop parameter, and the current mark token in the markToken parameter. The newStart and newStop parameters identify the beginning and end of the new set of marked objects that the mark-adjusting function will create by unmarking those previously marked objects that are not included in the new set. When the Apple Event Manager calls your mark-adjusting function, your application must dispose of any data structures that it may have created in order to mark the previously marked objects. The Apple Event Manager will call your mark-adjusting function only once for a given mark token. 
  5025. A mark token is valid until the Apple Event Manager either disposes of it (by calling AEDisposeToken) or returns it as the result of the AEResolve function. If the final result of a call to the AEResolve function is a mark token, the Apple event objects currently marked for that mark token are those specified by the object specifier record passed to AEResolve, and your application can proceed to do whatever the Apple event has requested. Note that your application is responsible for disposing of a final mark token with a call to AEDisposeToken, just as for any other final token.
  5026. If your application supports marking, it should also provide a token disposal function. When the Apple Event Manager calls AEDisposeToken to dispose of a mark token that is not the final result of a call to AEResolve, the subsequent call to your token disposal function lets you know that you can unmark the Apple event objects marked with that mark token. A call to AEDisposeDesc to dispose of a mark token (which would occur if you did not provide a token disposal function) would go unnoticed.  
  5027. 2
  5028. 2The Apple Event Manager
  5029. Reference to the Apple Event Manager
  5030. This section describes the basic data structures and all the routines that are specific to the Apple Event Manager. It also provides examples of application-defined object accessor functions and object callback functions that a server application might provide for use by AEResolve in resolving object specifier records. The first section, “Data Structures,” shows the Pascal data structures for the descriptor records and descriptor lists that provide the fundamental building blocks from which an Apple event is constructed. “Apple Event Manager Routines,” which begins on page 2-183, describes the Apple Event Manager routines you use to create, send, receive, and process Apple events. “Application-Defined Functions,” which begins on page 2-254, provides examples of object accessor functions and object callback functions that a server application might provide.
  5031. Data Structures
  5032. Descriptor records are the fundamental data structures from which Apple events are constructed. A descriptor record is a data structure of type AEDesc:
  5033. TYPE AEDesc = 
  5034.     RECORD                                            {descriptor record}
  5035.         descriptorType:                        DescType;                {type of data being passed}
  5036.         dataHandle:                         Handle;                {handle to data being passed}
  5037.     END;
  5038. descriptorType    A four-character string of type DescType (which in turn is of type ResType) that indicates the type of data being passed.
  5039. dataHandle    A handle to the data being passed.
  5040. Apple event attributes, Apple event parameters, object specifier records, tokens, and almost all the other data structures defined by the Apple Event Manager consist of one or more descriptor records. The Apple Event Manager identifies the various components of an Apple event by means of keywords associated with the corresponding descriptor records. The AEKeyword data type is defined as a four-character code:
  5041. TYPE        AEKeyword = PACKED ARRAY[1..4] OF Char;
  5042. Constants are typically used for keywords. A keyword combined with a descriptor record forms a keyword-specified descriptor record, which is defined by a data structure of type AEKeyDesc:
  5043. TYPE        AEKeyDesc =     
  5044.         RECORD
  5045.             descKey:                    AEKeyword;                    {keyword}
  5046.             descContent:                    AEDesc;                    {descriptor record}
  5047.         END;
  5048. descKey    A four-character code of type AEKeyword that identifies the data in the descContent field.
  5049. descContent    A descriptor record of type AEDesc.
  5050. Most the other data structures defined by the Apple Event Manager consist of combinations of descriptor records and keyword-specified descriptor records. For information about specific keywords and the data structures constructed or coerced from descriptor records of type AEDesc, see “Data Structures Within Apple Events,” which begins on page 2-17. Other data structures defined by the AppleEvent Manager are described in the next section, “Apple Event Manager Routines,” under the routines that use them.
  5051. Apple Event Manager Routines
  5052. This section describes routines for creating and managing Apple event and object accessor dispatch tables, getting information from Apple events, creating Apple events, creating and resolving object specifier records, sending Apple events, disposing of descriptor records and tokens, and coercing descriptor types. 
  5053. Creating and Managing the Apple Event Dispatch Tables
  5054. An Apple event dispatch table contains entries that specify the event class and event ID that refer to one or more Apple events, the address of the handler routine that handles those Apple events, and a reference constant. You can use the AEInstallEventHandler function to add entries to the Apple event dispatch table. This function sets up the initial mapping between the handlers in your application and the Apple events that they handle.
  5055. To get the address of a handler currently in the Apple event dispatch table, use the AEGetEventHandler function. If you need to remove any of your Apple event handlers after the mapping is established, you can use the AERemoveEventHandler function. 
  5056. 2AEInstallEventHandler
  5057. You can use the AEInstallEventHandler function to add an entry to either your application’s Apple event dispatch table or the system Apple event dispatch table.
  5058. FUNCTION AEInstallEventHandler (theAEEventClass: AEEventClass;
  5059.                                           theAEEventID: AEEventID; 
  5060.                                           handler: EventHandlerProcPtr; 
  5061.                                           handlerRefcon: LongInt;
  5062.                                           isSysHandler: Boolean): OSErr;
  5063. theAEEventClass
  5064. The event class for the Apple event or events to be dispatched for this entry. The AEEventClass data type is defined as a four-character code:
  5065.     TYPE                                     AEEventClass = PACKED ARRAY[1..4] OF Char;
  5066. theAEEventID
  5067. The event ID for the Apple event or events to be dispatched for this entry. The AEEventID data type is defined as a four-character code:
  5068.     TYPE                                     AEEventID = PACKED ARRAY[1..4] OF Char;
  5069. handler     A pointer to an Apple event handler for this dispatch table entry. Note that a handler in the system dispatch table must reside in the system heap; this means that if the value of the isSysHandler parameter is TRUE, the handler parameter should point to a location in the system heap. Otherwise, if you put your system handler code in your application heap, you must remove the handler before your application terminates by using the AERemoveEventHandler function.
  5070. handlerRefcon 
  5071. A reference constant that is passed by the Apple Event Manager to the handler each time the handler is called. If your handler doesn’t use a reference constant, use 0 as the value of this parameter. 
  5072. isSysHandler 
  5073. Specifies the Apple event dispatch table to which you want to add the handler. If the value of isSysHandler is TRUE, the Apple Event Manager adds the handler to the system Apple event dispatch table. Entries in the system Apple event dispatch table are available to all applications. If the value of isSysHandler is FALSE, the Apple Event Manager adds the handler to your application’s Apple event dispatch table. The application’s Apple event dispatch table is searched first; the system Apple event dispatch table is searched only if the necessary handler is not found in your application’s Apple event dispatch table.
  5074. DESCRIPTION
  5075. AEInstallEventHandler creates an entry in the Apple event dispatch table. You must supply parameters that specify the event class, event ID, and address of the handler routine that handles Apple events of the specified event class and event ID, and whether the handler is to be added to the system Apple event dispatch table or your application’s Apple event dispatch table. You can also specify a reference constant that the Apple Event Manager passes to your handler whenever your handler processes an Apple event.
  5076. The parameters theAEEventClass and theAEEventID specify the event class and event ID of the Apple events to be handled by the handler for this dispatch table entry. For these parameters, you must provide one of the following combinations:
  5077. n    the event class and event ID of a single Apple event to be dispatched to the handler
  5078. n    the typeWildCard constant for theAEEventClass and an event ID for theAEEventID, which indicates that Apple events from all event classes whose event IDs match theAEEventID should be dispatched to the handler
  5079. n    an event class for theAEEventClass and the typeWildCard constant for theAEEventID, which indicates that all events from the specified event class should be dispatched to the handler
  5080. n    the typeWildCard constant for both the theAEEventClass and theAEEventID parameters, which indicates that all Apple events should be dispatched to the handler 
  5081. If you use the typeWildCard constant for either the theAEEventClass or the theAEEventID parameter (or for both parameters), the corresponding handler must return the error errAEEventNotHandled if it does not handle a particular event.<36pt\>\x12 <8bat\>s
  5082. If there was already an entry in the specified Apple event handler dispatch table for the same event class and event ID, it is replaced. Therefore, before installing a handler for a particular Apple event in the system dispatch table, use the AEGetEventHandler function to determine whether the table already contains a handler for that event. If an entry exists, AEGetEventHandler returns a reference constant and a pointer to that event handler. Chain these to your event handler by providing pointers to the previous handler and its reference constant in the handlerRefcon parameter of AEInstallEventHandler. When your handler is finished, use these pointers to call the previous handler. If you remove your system handler, be sure to reinstall the chained handlers.
  5083. When an application calls a system Apple event handler, the A5 register is set up for the calling application. For this reason, if you provide a system Apple event handler, it should never use A5 global variables or anything that depends on a particular context; otherwise, the application that calls the system handler may crash.<36pt\>\x12 <8bat\>u
  5084. RESULT CODES
  5085. noErr    0    No error
  5086. paramErr    –50    Parameter error (handler pointer is NIL or odd)
  5087. memFullErr    –108    Not enough room in heap zone
  5088. SEE ALSO
  5089. For more information about installing Apple event handlers, see “Installing Entries in the Apple Event Dispatch Tables,” which begins on page 2-63.
  5090. 2AEGetEventHandler
  5091. You can use the AEGetEventHandler function to get an entry from an Apple event dispatch table.
  5092. FUNCTION AEGetEventHandler (theAEEventClass: AEEventClass; 
  5093.                                      theAEEventID: AEEventID; 
  5094.                                      VAR handler: EventHandlerProcPtr; 
  5095.                                         VAR handlerRefcon: LongInt; 
  5096.                                      isSysHandler: Boolean): OSErr;
  5097. theAEEventClass
  5098. The value of the event class field of the dispatch table entry for the desired Apple event handler.
  5099. theAEEventID
  5100. The value of the event ID field of the dispatch table entry for the desired Apple event handler.
  5101. handler    TheAEGetEventHandler function returns a pointer to the desired Apple event handler in this parameter.
  5102. handlerRefcon
  5103. The AEGetEventHandler function returns the reference constant from the object accessor dispatch table entry for the specified Apple event handler in this parameter.
  5104. isSysHandler 
  5105. Specifies the Apple event dispatch table from which to get the handler. If isSysHandler is TRUE, the AEGetEventHandler function returns the handler from the system dispatch table. If isSysHandler is FALSE, AEGetEventHandler returns the handler from your application’s dispatch table.
  5106. DESCRIPTION
  5107. AEGetEventHandler returns a pointer in the handler parameter to the handler for the Apple event dispatch table entry you specify in the parameters theAEEventClass and theAEEventID. You can use the typeWildCard constant for either or both of these parameters; however, AEGetEventHandler will return an error unless an entry exists that specifies typeWildCard in exactly the same way. For example, if you specify typeWildCard in both the theAEEventClass parameter and the theAEEventID parameter, the Apple Event Manager will not return the first handler for any event class and event ID in the dispatch table; instead, the dispatch table must contain an entry that specifies type typeWildCard for both the event class and the event ID, or else AEGetEWventHandler will return an error. 
  5108. RESULT CODES
  5109. noErr    0    No error
  5110. errAEHandlerNotFound    –1717    No handler found for an Apple event
  5111. SEE ALSO
  5112. For an explanation of wildcard values, see the description of the AEInstallEventHandler function on page 2-184.
  5113. 2AERemoveEventHandler
  5114. You can use the AERemoveEventHandler function to remove an entry from an Apple event dispatch table.
  5115. FUNCTION AERemoveEventHandler (theAEEventClass: AEEventClass; 
  5116.                                          theAEEventID: AEEventID; 
  5117.                                          handler: EventHandlerProcPtr; 
  5118.                                          isSysHandler: Boolean): OSErr;
  5119. theAEEventClass
  5120. The event class for the handler whose entry you want to remove from the Apple event dispatch table.
  5121. theAEEventID
  5122. The event ID for the handler whose entry you want to remove from the Apple event dispatch table.
  5123. handler    A pointer to the Apple event handler to be removed. Although the parameters theAEEventClass and theAEEventID would be sufficient to identify the handler to be removed, providing the handler parameter is a safeguard that ensures that you remove the correct handler.
  5124. isSysHandler 
  5125. Specifies the Apple event dispatch table from which to remove the handler. If isSysHandler is TRUE, AERemoveEventHandler removes the handler from the system dispatch table. If isSysHandler is FALSE, AERemoveEventHandler removes the handler from your application’s dispatch table.
  5126. DESCRIPTION
  5127. AERemoveEventHandler removes the Apple event dispatch table entry you specify in theparameters theAEEventClass, theAEEventID, and handler. You can use the typeWildCard constant for the theAEEventClass or the theAEEventID parameter, or for both parameters; however, AERemoveEventHandler will return an error unless an entry exists that specifies typeWildCard in exactly the same way. For example, if you specify typeWildCard in both the theAEEventClass parameter and the theAEEventID parameter, the Apple Event Manager will not remove the first handler for any event class and event ID in the dispatch table; instead, the dispatch table must contain an entry that specifies type typeWildCard for both the event class and the event ID, or else AERemoveEventHandler will return an error. 
  5128. SEE ALSO
  5129. For an explanation of wildcard values, see the description of the AEInstallEventHandler function on page 2-184.
  5130. RESULT CODES
  5131. noErr    0    No error
  5132. errAEHandlerNotFound    –1717    No handler found for an Apple event
  5133. Initializing the Object Support Library
  5134. You should call the AEObjectInit function to initialize the Apple Event Manager routines that handle object specifier records and Apple event objects. To make these routines available to your application, you must also link the Apple Event Object Support Library with your application when you build it. 
  5135. 2AEObjectInit
  5136. You use the AEObjectInit function to initialize the Object Support Library.
  5137. FUNCTION AEObjectInit : OSErr; 
  5138. DESCRIPTION
  5139. You must call this function before calling any of the Apple Event Manager routines that describe or manipulate Apple event objects.
  5140. RESULT CODES
  5141. noErr    0    No error occurred
  5142. memFullErr    –108    Not enough room in heap zone
  5143. errAENewerVersion     –1706    Need a newer version of the Apple Event 
  5144.         Manager
  5145. Setting Object Accessor Functions and Object Callback Functions
  5146. The Apple Event Manager provides two routines that allow you to specify the object accessor functions and object callback functions provided by your application. The AEInstallObjectAccessor function adds an entry for an object accessor function to either the application’s object accessor dispatch table or the system object accessor dispatch table. The AESetObjectCallbacks function allows you to specify the object callback functions to be called for your application. 
  5147. 2AEInstallObjectAccessor
  5148. You can use the AEInstallObjectAccessor function to add an entry for an object accessor function to either the application’s object accessor dispatch table or the system object accessor dispatch table.  
  5149. FUNCTION AEInstallObjectAccessor (desiredClass: DescType; 
  5150.                                             containerType: DescType; 
  5151.                                             theAccessor: AccessorProcPtr; 
  5152.                                             accessorRefcon: LongInt; 
  5153.                                             isSysHandler: Boolean): OSErr;
  5154. desiredClass
  5155. The object class of the Apple event objects that the object accessor function to be dispatched for this table entry can locate.
  5156. containerType
  5157. The descriptor type of the token used to specify the container for the desired objects. The object accessor function finds objects in containers specified by tokens of this type.
  5158. theAccessor
  5159. A pointer to the object accessor function for this table entry.
  5160. accessorRefcon
  5161. A reference constant passed by the Apple Event Manager to the object accessor function whenever the function is called. If your object accessor function doesn’t use a reference constant, use 0 as the value of this parameter.
  5162. isSysHandler
  5163. Specifies the object accessor dispatch table to which you add the object accessor function. If the value of isSysHandler is TRUE, the Apple Event Manager adds the routine to the system object accessor table. Entries in the system object accessor table are available to all applications running on the same computer. If the value of isSysHandler is FALSE, the Apple Event Manager adds the routine to your application’s object accessor table. The application accessor table is searched first; the system accessor table is searched only if the necessary function is not found in your application’s object accessor table.
  5164. DESCRIPTION
  5165. AEInstallObjectAccessor adds an entry to either the application or system object accessor table. You must supply parameters that specify the object class of the Apple event objects that the object accessor function can locate, the descriptor type of tokens for containers in which the object accessor function can locate objects, the address of the object accessor function for which you are adding an entry, and whether the entry is to be added to the system object accessor dispatch table or your application’s object accessor dispatch table. You can also specify a reference constant that the Apple Event Manager passes to your object accessor function each time the Apple Event Manager calls the function.
  5166. Note that an object accessor function in the system object accessor dispatch table must reside in the system heap; this means that if the value of the isSysHandler parameter is TRUE, the handler parameter must point to a location in the system heap.
  5167. RESULT CODES
  5168. noErr    0    No error occurred
  5169. paramErr    –50    The handler pointer is NIL or odd, or
  5170.         AEObjectInit was not called before this 
  5171.         function
  5172. SEE ALSO
  5173. For more information about installing object accessor functions, see “Installing Entries in the Object Accessor Dispatch Tables,” which begins on page 2-66.  
  5174. 2AESetObjectCallbacks
  5175. You can use the AESetObjectCallbacks function to specify the object callback functions to be called for your application.  
  5176. FUNCTION AESetObjectCallbacks (myCompareProc,myCountProc, 
  5177.                                             myDisposeTokenProc, 
  5178.                                             myGetMarkTokenProc,myMarkProc, 
  5179.                                             myAdjustMarksProc,reserved: 
  5180.                                             ProcPtr): OSErr;
  5181. myCompareProc
  5182. Either a pointer to the object comparison function provided by your application or NIL if no function is provided.
  5183. myCountProc
  5184. Either a pointer to the object counting function provided by your application or NIL if no function is provided.
  5185. myDisposeTokenProc
  5186. Either a pointer to the token disposal function provided by your application or NIL if no function is provided.
  5187. myGetMarkTokenProc
  5188. Either a pointer to the function for returning a mark token provided by your application or NIL if no function is provided.
  5189. myMarkProc    Either a pointer to the object marking function provided by your application or NIL if no function is provided.
  5190. myAdjustMarksProc
  5191. Either a pointer to the mark adjusting function provided by your application or NIL if no function is provided.
  5192. MyGetErrDescProc
  5193. Either a pointer to the error callback function provided by your application or NIL if no function is provided.
  5194. DESCRIPTION
  5195. Your application can provide only one each of the object callback functions specified by AESetObjectCallbacks: one comparison function, one counting function, and so on. As a result, each of these callback functions must perform the requested task (comparing, counting, and so on) for all the object classes that your application supports. In contrast, your application may provide many different object accessor functions if necessary, depending on the object classes and token types your application supports.
  5196. To replace object callback routines that have been previously installed, you can make another call to AESetObjectCallbacks. You can only do this to replace routines that can be installed by AESetObjectCallbacks; you cannot use AESetObjectCallbacks to replace system object callback routines or object accessor functions. Only those routines you specify are replaced; if you provide a value of NIL for any routine, the currently installed routine (if any) remains installed.
  5197. RESULT CODES
  5198. noErr    0    No error occurred
  5199. paramErr    –50    The handler pointer is NIL or odd, or 
  5200.         AEObjectInit was not called before 
  5201.         this function
  5202. memFullErr    –108    There is not enough room in heap zone
  5203. errAENotASpecialFunction    –1714    The keyword is not a valid keyword for a 
  5204.         special function
  5205. SEE ALSO
  5206. For examples of object callback functions that your application might provide, see “Application-Defined Functions,” which begins on page 2-254.
  5207. To install system object callback functions, use the AEInstallSpecialHandler function described on page 2-251.  
  5208. Getting, Calling, and Removing Object Accessor Functions
  5209. The Apple Event Manager provides three routines that allow you to get, call, and remove object accessor functions that you have installed in either the system or application object accessor dispatch table with the AEInstallObjectAccessor function. The AEGetObjectAccessor function allows you to get a pointer to an object accessor function and the value of its reference constant. The AECallObjectAccessor function allows you to invoke one of your object accessor functions. The AERemoveObjectAccessor function allows you to remove an object accessor function from an object accessor dispatch table.
  5210. 2AEGetObjectAccessor
  5211. You can use the AEGetObjectAccessor function to get a pointer to an object accessor function and the value of its reference constant. 
  5212. FUNCTION AEGetObjectAccessor (desiredClass: DescType; 
  5213.                                         containerType: DescType;
  5214.                                         VAR theAccessor: AccessorProcPtr;
  5215.                                         VAR accessorRefcon: LongInt; 
  5216.                                         isSysHandler: Boolean): OSErr;
  5217. desiredClass
  5218. The object class of the Apple event objects located by the requested object accessor function. This parameter can also contain the constant typeWildCard or the constant cProperty.
  5219. containerType
  5220. The descriptor type of the token that identifies the container for the Apple event objects located by the requested object accessor function. This parameter can also contain the constant typeWildCard.
  5221. theAccessor
  5222. The AEGetObjectAccessor function returns a pointer to the requested object accessor function in this parameter.
  5223. accessorRefcon    
  5224. The AEGetObjectAccessor function returns the reference constant from the object accessor dispatch table entry for the specified object accessor function in this parameter.
  5225. isSysHandler
  5226. Specifies the object accessor table from which to get the object accessor function and its reference constant. If isSysHandler is TRUE, AEGetObjectAccessor gets the function from the system object accessor dispatch table. If isSysHandler is FALSE, AEGetObjectAccessor gets the function from the application’s object accessor dispatch table.
  5227. DESCRIPTION
  5228. AEGetObjectAccessor returns a pointer to the object accessor function installed for the object class specified in the desiredClass parameter and the descriptor type specified in the containerType parameter. AEGetObjectAccessor also returns the reference constant associated with the specified function. You must supply a value in the isSysHandler parameter that specifies which object accessor dispatch table you want to get the function from. 
  5229. Calling AEGetObjectAccessor does not remove the object accessor function from an object accessor dispatch table.
  5230. To get an object accessor function whose entry in an object accessor dispatch table specifies typeWildCard as the object class, you must specify typeWildCard as the value of the desiredClass parameter. Similarly, to get an object accessor function whose entry in an object accessor dispatch table specifies typeWildCard as the descriptor type of the token used to specify the container for the desired objects, you must specify typeWildCard as the value of the containerType parameter.
  5231. To get an object accessor function whose entry in an object accessor dispatch table specifies cProperty (a constant used to specify a property of any object class), you must specify cProperty as the desiredClass parameter. 
  5232. RESULT CODES
  5233. noErr    0    No error occurred
  5234. paramErr    –50    AEObjectInit was not called before 
  5235.         this function was called
  5236. errAEAccessorNotFound    –1723    There is no object accessor function for 
  5237.         the specified object class and container 
  5238.                 type  
  5239. 2AECallObjectAccessor
  5240. You can use the AECallObjectAccessor function to invoke one of your application’s object accessor functions. 
  5241. FUNCTION AECallObjectAccessor (desiredClass: DescType; 
  5242.                                             containerToken: AEDesc; 
  5243.                                             containerClass: DescType; 
  5244.                                             keyForm: DescType; 
  5245.                                             keyData: AEDesc; 
  5246.                                             VAR theToken: AEDesc): OSErr;
  5247. desiredClass
  5248. The object class of the requested Apple event objects.
  5249. containerToken
  5250. The token that identifies the container for the desired Apple event objects.
  5251. containerClass
  5252. The object class of the container for the desired Apple event objects.
  5253. keyForm    The key form specified by the object specifier record for the object or objects to be located.
  5254. keyData    The key data specified by the object specifier record for the object or objects to be located.
  5255. theToken    The object accessor function that is invoked returns a token specifying the desired object or objects in this parameter.
  5256. DESCRIPTION
  5257. If you want your application to do some of the Apple event object resolution normally performed by the AEResolve function, you can use AECallObjectAccessor to invoke an object accessor function. This might be useful, for example, when you have installed an object accessor function in an object accessor dispatch table by specifying the constant typeWildCard for the AEInstallObjectAccessor function’s desiredClass parameter, containerType parameter, or both parameters. Your application can take care of some initial processing that is the same for all incoming requests and then call AEResolve to do the rest.
  5258. The parameters of AECallObjectAccessor are identical to the parameters of an object accessor function, with one exception: the parameter that specifies the reference constant passed to the object accessor function whenever it is called is added by the Apple Event Manager when it calls the object accessor function.
  5259. To call an object accessor function whose entry in an object accessor dispatch table specifies typeWildCard as the object class, you must specify typeWildCard as the value of the desiredClass parameter. 
  5260. To call an object accessor function whose entry in an object accessor dispatch table specifies cProperty, you must specify cProperty as the desiredClass parameter. 
  5261. RESULT CODES
  5262. In addition to the following result codes, AECallObjectAccessor returns any other result codes returned by the object accessor function that is called.
  5263. noErr    0    No error occurred.
  5264. paramErr    –50    AEObjectInit was not called before 
  5265.         calling this function.
  5266. errAEEventNotHandled    –1708    No object accessor was found. 
  5267. 2AERemoveObjectAccessor
  5268. You can use the AERemoveObjectAccessor function to remove an object accessor function from an object accessor dispatch table.  
  5269. FUNCTION AERemoveObjectAccessor (desiredClass: DescType; 
  5270.                                             containerType: DescType; 
  5271.                                             theAccessor: AccessorProcPtr; 
  5272.                                             isSysHandler: Boolean): OSErr;
  5273. desiredClass
  5274. The object class of the Apple event objects located by the object accessor function. The desiredClass parameter can also contain the constant typeWildCard or the constant cProperty.
  5275. containerType
  5276. The descriptor type of the token that identifies the container for the Apple event objects located by the object accessor function. The containerType can also contain the constant typeWildCard.
  5277. theAccessor
  5278. A pointer to the object accessor function you want to remove. Although the parameters desiredClass and containerClass would be sufficient to identify the function to be removed, providing the parameter theAccessor guarantees that you remove the correct function. If this parameter does not contain a pointer to the object accessor function you want to remove, its value should be NIL.
  5279. isSysHandler
  5280. Specifies the object accessor dispatch table from which to delete the object accessor function. If isSysHandler is TRUE, AEGetObjectAccessor removes the routine from the system object accessor dispatch table. If isSysHandler is FALSE, AEGetObjectAccessor removes the routine from the application object accessor dispatch table.
  5281. DESCRIPTION
  5282. AERemoveObjectAccessor removes the object accessor function you have installed for the object class specified in the desiredClass parameter and the descriptor type specified in the containerType parameter. 
  5283. To remove an object accessor function whose entry in an object accessor dispatch table specifies typeWildCard as the object class, you must specify typeWildCard as the value of the desiredClass parameter. Similarly, to remove an object accessor function whose entry in an object accessor dispatch table specifies typeWildCard as the descriptor type of the token used to specify the container for the desired objects, you must specify typeWildCard as the value of the containerType parameter.
  5284. To remove an object accessor function whose entry in an object accessor dispatch table specifies cProperty (a constant used to specify a property of any object class), you must specify cProperty as the desiredClass parameter. 
  5285. RESULT CODES
  5286. noErr    0    No error occurred.
  5287. paramErr    –50    AEObjectInit was not called before 
  5288.         calling this function.
  5289. errAEAccessorNotFound    –1723    There is no object accessor function for 
  5290.         the specified object class and container 
  5291.         type.  
  5292. Dispatching Apple Events
  5293. After receiving a high-level event (and optionally determining whether it is a type of high-level event other than an Apple event that your application might support), your application typically calls the AEProcessAppleEvent function to determine the type of Apple event received and call the corresponding handler.
  5294. 2AEProcessAppleEvent
  5295. You can use the AEProcessAppleEvent function to call the appropriate handler in your application for a specified Apple event. 
  5296. FUNCTION AEProcessAppleEvent 
  5297.                                 (theEventRecord: EventRecord): OSErr;
  5298. theEventRecord
  5299. The event record for the Apple event.
  5300. DESCRIPTION
  5301. The AEProcessAppleEvent function looks first in the application’s special handler dispatch table for an entry that was installed with the constant keyPreDispatch. If the application’s special handler dispatch table does not include such a handler or if the handler returns errAEEventNotHandled, the function looks in the application’s Apple event dispatch table for an entry that matches the event class and event ID of the specified Apple event. 
  5302. If the application’s Apple event dispatch table does not include such a handler or if the handler returns errAEEventNotHandled, the AEProcessAppleEvent function looks in the system special handler dispatch table for an entry that was installed with the constant keyPreDispatch. If the system special handler dispatch table does not include such a handler or if the handler returns errAEEventNotHandled, the function looks in the system Apple event dispatch table for an entry that matches the event class and event ID of the specified Apple event. 
  5303. If the system special handler dispatch table does not include such a handler, the Apple Event Manager returns the result code errAEEventNotHandled to the server application and, if the client application is waiting for a reply, to the client application.
  5304. If an Apple dispatch table contains one entry for an event class and a specific event ID, and also contains another entry that is identical except that it specifies a wildcard value for either the event class or the event ID, the Apple Event Manager will dispatch the more specific entry. For example, if an Apple event dispatch table includes one entry that specifies the event class as kAECoreSuite and the event ID as kAEDelete, and another entry that specifies the event class as kAECoreSuite and the event ID as typeWildCard, the Apple Event Manager will dispatch the Apple event handler associated with the entry that specifies the event ID as kAEDelete.
  5305. RESULT CODES
  5306. noErr    0    No error
  5307. memFullErr    –108    Not enough room in heap zone
  5308. bufferIsSmall    –607    Buffer is too small
  5309. noOutstandingHLE    –608    No outstanding high-level event
  5310. errAECorruptData    –1702    Data in an Apple event could not be read
  5311. errAENewerVersion    –1706    Need a newer version of the Apple Event
  5312.                 Manager
  5313. errAEEventNotHandled    –1708    Event wasn’t handled by an Apple event 
  5314.             handler
  5315. Getting Data or Descriptor Records from Apple Event Parameters and Attributes
  5316. The Apple Event Manager provides four functions that allow you to get data from Apple event parameters and attributes. The AEGetParamPtr and AEGetParamDesc functions get data from a specified Apple event parameter. The AEGetAttributePtr and AEGetAttributeDesc functions get data from a specified Apple event attribute. 
  5317. 2AEGetParamPtr
  5318. You can use the AEGetParamPtr function to get a pointer to a buffer that contains the data from a specified Apple event parameter.
  5319. FUNCTION AEGetParamPtr (theAppleEvent: AppleEvent; 
  5320.                                     theAEKeyword: AEKeyword;
  5321.                                 desiredType: DescType; 
  5322.                                 VAR typeCode: DescType; dataPtr: Ptr; 
  5323.                                 maximumSize: Size; 
  5324.                                 VAR actualSize: Size): OSErr;
  5325. theAppleEvent
  5326. The Apple event containing the desired parameter.
  5327. theAEKeyword 
  5328. The keyword that specifies the desired parameter.
  5329. desiredType
  5330. The desired descriptor type for the data to be returned; if the requested Apple event parameter is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of the returned data is the same as the descriptor type of the Apple event parameter. 
  5331. typeCode         The descriptor type of the returned data.
  5332. dataPtr     A pointer to the buffer in which the returned data is stored.
  5333. maximumSize 
  5334. The maximum length, in bytes, of the data to be returned. You must allocate at least this amount of storage for the buffer specified by the dataPtr parameter. 
  5335. actualSize    The length, in bytes, of the data for the specified Apple event parameter. If this value is larger than the value of the maximumSize parameter, not all of the data for the parameter was returned.
  5336. DESCRIPTION
  5337. The AEGetParamPtr function uses a buffer to return the data from a specified Apple event parameter, which it attempts to coerce to the descriptor type specified by the desiredType parameter. 
  5338. RESULT CODES
  5339. noErr    0    No error
  5340. memFullErr    –108    Not enough room in heap zone
  5341. errAECoercionFail     –1700    Data could not be coerced to the 
  5342.         requested descriptor type
  5343. errAEDescNotFound     –1701    Descriptor record was not found
  5344. errAEWrongDataType    –1703    Wrong descriptor type
  5345. errAENotAEDesc    –1704    Not a valid descriptor record
  5346. errAEReplyNotArrived    –1718    Reply has not yet arrived
  5347. 2AEGetParamDesc
  5348. You can use the AEGetParamDesc function to get the descriptor record for a specified Apple event parameter.  
  5349. FUNCTION AEGetParamDesc (theAppleEvent: AppleEvent; theAEKeyword: 
  5350.                                  AEKeyword; desiredType: DescType; 
  5351.                                  VAR result: AEDesc): OSErr;
  5352. theAppleEvent 
  5353. The Apple event containing the desired parameter.
  5354. theAEKeyword 
  5355. The keyword that specifies the desired parameter.
  5356. desiredType 
  5357. The desired descriptor type for the descriptor record to be returned; if the requested Apple event parameter is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of the returned data is the same as the descriptor type of the Apple event parameter. 
  5358. result     The descriptor record from the desired Apple event parameter coerced to the descriptor type specified in desiredType.
  5359. DESCRIPTION
  5360. The AEGetParamDesc function returns the descriptor record for a specified Apple event parameter, which it attempts to coerce to the descriptor type specified by the desiredType parameter. Your application should call the AEDisposeDesc function to dispose of the resulting descriptor record after your application has finished using it.
  5361. If AEGetParamDesc returns a nonzero result code, it returns a null descriptor record (a descriptor record of type typeNull, which does not contain any data) unless the Apple Event Manager is not available due to limited memory.
  5362. RESULT CODES
  5363. noErr    0    No error
  5364. memFullErr    –108    Not enough room in heap zone
  5365. errAECoercionFail     –1700    Data could not be coerced to the requested 
  5366.         descriptor type
  5367. errAEDescNotFound     –1701    Descriptor type was not found
  5368. errAENotAEDesc    –1704    Not a valid descriptor record
  5369. errAEReplyNotArrived    –1718    Reply has not yet arrived
  5370. 2AEGetAttributePtr
  5371. You can use the AEGetAttributePtr function to get a pointer to a buffer that contains the data from a specified Apple event attribute.
  5372. FUNCTION AEGetAttributePtr (theAppleEvent: AppleEvent; 
  5373.                                      theAEKeyword: AEKeyword; 
  5374.                                      desiredType: DescType; 
  5375.                                         VAR typeCode: DescType; dataPtr: Ptr; 
  5376.                                         maximumSize: Size; 
  5377.                                      VAR actualSize: Size): OSErr;
  5378. theAppleEvent
  5379. The Apple event containing the desired attribute.
  5380. theAEKeyword
  5381. The keyword that specifies the desired attribute.
  5382. desiredType    
  5383. The desired descriptor type for the data to be returned; if the requested Apple event attribute is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of the returned data is the same as the descriptor type of the Apple event attribute. 
  5384. typeCode    The descriptor type of the returned data.
  5385. dataPtr     A pointer to the buffer in which the returned data is stored.
  5386. maximumSize 
  5387. The maximum length, in bytes, of the data to be returned. You must allocate at least this amount of storage for the buffer specified by the dataPtr parameter. 
  5388. actualSize    The length, in bytes, of the data for the specified Apple event attribute. If this value is larger than the value of the maximumSize parameter, not all of the data for the attribute was returned.
  5389. DESCRIPTION
  5390. The AEGetAttributePtr function uses a buffer to return the data from an Apple event attribute with the specified keyword, which it attempts to coerce to the descriptor type specified by the desiredType parameter. The keyword can be one of the following:
  5391. Attribute keyword        Value    Description
  5392. keyAddressAttr         'addr'    Address of target application
  5393. keyEventClassAttr         'evcl'    Event class of Apple event
  5394. keyEventIDAttr        'evid'    Event ID of Apple event
  5395. keyEventSourceAttr        'esrc'    Source of the Apple event
  5396. keyInteractLevelAttr         'inte'    Settings for allowing the Apple Event
  5397.             Manager to bring a server application
  5398.             to the foreground
  5399. keyMissedKeywordAttr        'miss'    First required parameter remaining in
  5400.             an Apple event
  5401. keyOptionalKeywordAttr        'optk'    List of optional parameters
  5402.             for the Apple event
  5403. keyReturnIDAttr         'rtid'    Return ID for reply Apple event 
  5404. keyTimeoutAttr        'timo'    Length of time in ticks that the client
  5405.             will wait for a reply or a result from
  5406.             the server
  5407. keyTransactionIDAttr         'tran'    Transaction ID identifying a series of 
  5408.             Apple events
  5409. RESULT CODES
  5410. noErr    0    No error
  5411. memFullErr    –108    Not enough room in heap zone
  5412. errAECoercionFail     –1700    Data could not be coerced to the requested 
  5413.         descriptor type
  5414. errAEDescNotFound     –1701    Descriptor type was not found
  5415. errAENotAEDesc    –1704    Not a valid descriptor record
  5416. errAEReplyNotArrived    –1718    Reply has not yet arrived
  5417. 2AEGetAttributeDesc
  5418. You can use the AEGetAttributeDesc function to get the descriptor record for a specified Apple event attribute.   
  5419. FUNCTION AEGetAttributeDesc (theAppleEvent: AppleEvent; 
  5420.                                       theAEKeyword: AEKeyword; 
  5421.                                       desiredType: DescType; 
  5422.                                           VAR result: AEDesc): OSErr;
  5423. theAppleEvent
  5424. The Apple event containing the desired attribute.
  5425. theAEKeyword 
  5426. The keyword that specifies the desired parameter.
  5427. desiredType 
  5428. The desired descriptor type for the descriptor record to be returned; if the requested Apple event attribute is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of the returned data is the same as the descriptor type of the Apple event attribute. 
  5429. result     A copy of the descriptor record from the desired attribute coerced to the descriptor type specified by the desiredType parameter.
  5430. DESCRIPTION
  5431. The AEGetAttributeDesc function returns the descriptor record for the Apple event attribute with the specified keyword . Your application should call the AEDisposeDesc function to dispose of the resulting descriptor record after your application has finished using it.
  5432. The keyword can be one of the following:
  5433. Attribute keyword        Value    Description
  5434. keyAddressAttr         'addr'    Address of target application
  5435. keyEventClassAttr         'evcl'    Event class of Apple event
  5436. keyEventIDAttr        'evid'    Event ID of Apple event
  5437. keyEventSourceAttr        'esrc'    Source of the Apple event
  5438. keyInteractLevelAttr         'inte'    Settings for allowing the Apple Event
  5439.             Manager to bring a server application
  5440.             to the foreground
  5441. keyMissedKeywordAttr        'miss'    First required parameter remaining in
  5442.             an Apple event
  5443. keyOptionalKeywordAttr        'optk'    List of optional parameters
  5444.             for the Apple event
  5445. keyReturnIDAttr         'rtid'    Return ID for reply Apple event 
  5446. keyTimeoutAttr        'timo'    Length of time in ticks that the client
  5447.             will wait for a reply or a result from
  5448.             the server
  5449. keyTransactionIDAttr         'tran'    Transaction ID identifying a series of 
  5450.             Apple events
  5451. If AEGetAttributeDesc returns a nonzero result code, it returns a null descriptor record (a descriptor record of type typeNull, which does not contain any data) unless the Apple Event Manager is not available due to limited memory.
  5452. RESULT CODES
  5453. noErr    0    No error
  5454. memFullErr    –108    Not enough room in heap zone
  5455. errAECoercionFail     –1700    Data could not be coerced to the requested 
  5456.         descriptor type
  5457. errAEDescNotFound     –1701    Descriptor record was not found
  5458. errAENotAEDesc    –1704    Not a valid descriptor record
  5459. errAEReplyNotArrived    –1718    Reply has not yet arrived
  5460. Counting the Items in Descriptor Lists
  5461. The AECountItems function counts the number of descriptor records in any descriptor list, including an Apple event record.
  5462. 2AECountItems
  5463. You can use the AECountItems function to count the number of descriptor records in any descriptor list.
  5464. FUNCTION AECountItems (theAEDescList: AEDescList; 
  5465.                               VAR theCount:                     LongInt): OSErr;
  5466. theAEDescList
  5467. The descriptor list to be counted.
  5468. theCount    The number of descriptor records in the specified descriptor list.
  5469. RESULT CODES
  5470. noErr    0    No error
  5471. errAENotAEDesc    –1704    Not a valid descriptor record 
  5472. Getting Items From Descriptor Lists
  5473. The Apple Event Manager provides three functions that allow you to get items from any descriptor list, including an Apple event record. The AEGetNthPtr and AEGetNthDesc functions give you access to the data in a descriptor list. The AEGetArray function gets data from an array contained in a descriptor list.
  5474. 2AEGetNthPtr
  5475. You can use the AEGetNthPtr function to get a pointer to a buffer that contains a descriptor record from any descriptor list.
  5476. FUNCTION AEGetNthPtr (theAEDescList: AEDescList; index: LongInt; 
  5477.                              desiredType: DescType; VAR theAEKeyword: 
  5478.                              AEKeyword; VAR typeCode: DescType; 
  5479.                              dataPtr: Ptr; maximumSize: Size; 
  5480.                              VAR actualSize: Size): OSErr;
  5481. theAEDescList
  5482. The descriptor list containing the desired descriptor record.
  5483. index    The position of the desired descriptor record in the list (for example, 2 specifies the second descriptor record).
  5484. desiredType    
  5485. The desired descriptor type of the copy of the descriptor record; if the desired descriptor record is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of the copied descriptor record is the same as the descriptor type of the original descriptor record.
  5486. theAEKeyword
  5487. The keyword of the specified descriptor record, if you are getting data from a list of keyword-specified descriptor records; otherwise, AEGetNthPtr returns the value typeWildCard. 
  5488. typeCode    The descriptor type of the returned descriptor record.
  5489. dataPtr     A pointer to the buffer in which the returned descriptor record is stored.
  5490. maximumSize 
  5491. The maximum length, in bytes, of the data to be returned. You must allocate at least this amount of storage for the buffer specified by the dataPtr parameter.
  5492. actualSize    The length, in bytes, of the data for the specified descriptor record. If this value is larger than the value of the maximumSize parameter, not all of the data for the descriptor record was returned.
  5493. DESCRIPTION
  5494. The AEGetNthPtr function uses a buffer to return a specified descriptor record from a specified descriptor list; the function attempts to coerce the descriptor record to the descriptor type specified by the desiredType parameter.
  5495. RESULT CODES
  5496. noErr    0    No error
  5497. memFullErr    –108    Not enough room in heap zone
  5498. errAECoercionFail     –1700    Data could not be coerced to the requested 
  5499.         descriptor type
  5500. errAEDescNotFound     –1701    Descriptor record was not found
  5501. errAEWrongDataType    –1703    Wrong descriptor type
  5502. errAENotAEDesc    –1704    Not a valid descriptor record
  5503. errAEReplyNotArrived    –1718    Reply has not yet arrived
  5504. 2AEGetNthDesc
  5505. You can use the AEGetNthDesc function to get a descriptor record from any descriptor list. 
  5506. FUNCTION AEGetNthDesc (theAEDescList: AEDescList; index: LongInt; 
  5507.                                  desiredType: DescType; VAR theAEKeyword: 
  5508.                                  AEKeyword; VAR result: AEDesc): OSErr;
  5509. theAEDescList 
  5510. The descriptor list containing the desired descriptor record.
  5511. index     The position of the desired descriptor record in the list (for example, 2 specifies the second descriptor record).
  5512. desiredType     
  5513. The desired descriptor type for the copy of the descriptor record to be returned; if the desired descriptor record is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of the returned descriptor record is the same as the descriptor type of the original descriptor record.
  5514. theAEKeyword
  5515. The keyword of the specified descriptor record, if you are getting data from a list of keyword-specified descriptor records; otherwise, AEGetNthDesc returns the value typeWildCard. 
  5516. result    A copy of the desired descriptor record coerced to the descriptor type specified by the desiredType parameter.
  5517. DESCRIPTION
  5518. The AEGetNthDesc function returns a specified descriptor record from a specified descriptor list.Your application should call the AEDisposeDesc function to dispose of the resulting descriptor record after your application has finished using it.
  5519. If AEGetNthDesc returns a nonzero result code, it returns a descriptor record of descriptor type typeNull. A descriptor record of this type does not contain any data.
  5520. RESULT CODES
  5521. noErr    0    No error
  5522. memFullErr    –108    Not enough room in heap zone
  5523. errAECoercionFail     –1700    Data could not be coerced to the requested 
  5524.         descriptor type
  5525. errAEDescNotFound     –1701    Descriptor record was not found
  5526. errAENotAEDesc    –1704    Not a valid descriptor record
  5527. errAEReplyNotArrived    –1718    Reply has not yet arrived 
  5528. 2AEGetArray
  5529. You can use the AEGetArray function to convert an Apple event array (an array created with the AEPutArray function and stored in a descriptor list) into the corresponding Pascal or C array.
  5530. FUNCTION AEGetArray (theAEDescList: AEDescList; 
  5531.                             arrayType: AEArrayType; 
  5532.                              arrayPtr: AEArrayDataPointer; 
  5533.                             maximumSize: Size; 
  5534.                              VAR itemType: DescType; VAR itemSize: Size; 
  5535.                              VAR itemCount: LongInt): OSErr;
  5536. theAEDescList 
  5537. A factored descriptor list containing the desired array.
  5538. arrayType     The Apple event array type to be converted. This is specified by one of the following constants: kAEDataArray, kAEPackedArray, kAEHandleArray, kAEDescArray, or kAEKeyDescArray.
  5539. arrayPtr     A pointer to the buffer for storing the array.
  5540. maximumSize 
  5541. The maximum length, in bytes, of the buffer for storing the array.
  5542. itemType    For packed, data, and handle arrays, the AEGetArray function returns the descriptor type of the returned array items in this parameter.
  5543. itemSize    For packed and data arrays, the AEGetArray function returns the size, in bytes, of the returned array items in this parameter.
  5544. itemCount     The AEGetArray function returns the number of items in the resulting array in this parameter.
  5545. DESCRIPTION
  5546. The AEGetArray function converts the Apple event array specified by the theAEDescList parameter into the corresponding Pascal or C array. 
  5547. RESULT CODES
  5548. noErr    0    No error
  5549. memFullErr    –108    Not enough room in heap zone
  5550. errAEWrongDataType    –1703    Wrong descriptor type
  5551. errAENotAEDesc    –1704    Not a valid descriptor record
  5552. errAEReplyNotArrived    –1718    Reply has not yet arrived
  5553. Getting Data and Keyword-Specified Descriptor Records From AE Records
  5554. The AEGetKeyPtr and AEGetKeyDesc functions allow you to get data and keyword-specified descriptor records out of an AE record or an Apple event record.
  5555. 2AEGetKeyPtr
  5556. You can use the AEGetKeyPtr function to get a pointer to a buffer that contains the data from a keyword-specified descriptor record. You can use this function to get data out of an AE record or an Apple event record.
  5557. FUNCTION AEGetKeyPtr (theAERecord: AERecord; theAEKeyword: 
  5558.                              AEKeyword; desiredType: DescType; 
  5559.                              VAR typeCode: DescType; 
  5560.                              dataPtr: Ptr; maximumSize: Size; 
  5561.                              VAR actualSize: Size): OSErr;
  5562. theAERecord     
  5563. The AE record containing the desired data.
  5564. theAEKeyword
  5565. The keyword that specifies the desired descriptor record.
  5566. desiredType    
  5567. The desired descriptor type for the data to be returned; if the requested data is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of returned data is the same as the descriptor type of the original data. 
  5568. typeCode    The descriptor type of the returned data.
  5569. dataPtr     A pointer to the buffer for storing the data.
  5570. maximumSize 
  5571. The maximum length, in bytes, of the data to be returned. You must allocate at least this amount of storage for the buffer specified by the dataPtr parameter.
  5572. actualSize    The length, in bytes, of the data for the keyword-specified descriptor record. If this value is larger than the value of the maximumSize parameter, not all of the data for the parameter was returned.
  5573. DESCRIPTION
  5574. The AEGetKeyPtr function uses a buffer to return the data from a keyword-specified Apple event parameter, which it attempts to coerce to the descriptor type specified by the desiredType parameter. 
  5575. RESULT CODES
  5576. noErr    0    No error
  5577. memFullErr    –108    Not enough room in heap zone
  5578. errAECoercionFail     –1700    Data could not be coerced to the requested 
  5579.         descriptor type
  5580. errAEDescNotFound     –1701    Descriptor record was not found
  5581. errAEWrongDataType    –1703    Wrong descriptor type
  5582. errAENotAEDesc    –1704    Not a valid descriptor record
  5583. errAEReplyNotArrived    –1718    Reply has not yet arrived
  5584. 2AEGetKeyDesc
  5585. You can use the AEGetKeyDesc function to get the descriptor record for a keyword-specified descriptor record. You can use this function to get a descriptor record out of an AE record or an Apple event record.
  5586. FUNCTION AEGetKeyDesc (theAERecord: AERecord; 
  5587.                               theAEKeyword: AEKeyword; 
  5588.                                  desiredType: DescType; 
  5589.                               VAR result: AEDesc): OSErr;
  5590. theAERecord     
  5591. The AE record containing the desired descriptor record.
  5592. theAEKeyword    
  5593. The keyword that specifies the desired descriptor record.
  5594. desiredType    
  5595. The desired descriptor type for the descriptor record to be returned; if the requested descriptor record is not of this type, the Apple Event Manager attempts to coerce it into this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of the returned descriptor record is the same as the descriptor type of the original descriptor record.
  5596. result    A copy of the keyword-specified descriptor record, coerced to the descriptor type specified in the desiredType parameter. 
  5597. DESCRIPTION
  5598. The AEGetKeyDesc function returns a copy of the descriptor record for a keyword-specified descriptor record. Your application should call the AEDisposeDesc function to dispose of the resulting descriptor record after your application has finished using it. 
  5599. If AEGetKeyDesc returns a nonzero result code, it returns a descriptor record of descriptor type typeNull. A descriptor record of this type does not contain any data.
  5600. RESULT CODES
  5601. noErr    0    No error
  5602. memFullErr    –108    Not enough room in heap zone
  5603. errAECoercionFail     –1700    Data could not be coerced to the requested 
  5604.         descriptor type
  5605. errAEDescNotFound     –1701    Descriptor record was not found
  5606. errAENotAEDesc    –1704    Not a valid descriptor record
  5607. errAEReplyNotArrived    –1718    Reply has not yet arrived 
  5608. Resolving Object Specifier Records
  5609. If an Apple event parameter consists of an object specifier record, your handler for the event typically calls the AEResolve function to begin the process of resolving the object specifier record. 
  5610. 2AEResolve
  5611. You can use the AEResolve function to resolve an object specifier record in an Apple event parameter.
  5612. FUNCTION AEResolve (objectSpecifier: AEDesc; 
  5613.                             callbackFlags: Integer; 
  5614.                             VAR theToken: AEDesc): OSErr;
  5615. objectSpecifier
  5616. The object specifier record to be resolved.
  5617. callbackFlags
  5618. A value that determines what additional assistance, if any, your application can give the Apple Event Manager when it parses the object specifier record. The value is specified by adding the following constants, as appropriate:
  5619.                         CONST kAEIDoMinimum                                                     =     $0000 ; {Supports minimum }
  5620.                                                                                               { callbacks only}
  5621.                                       kAEIDoWhose                       =     $0001 ; {Supports formWhose}
  5622.                                       kAEIDoMarking                     =     $0004 ; {Provides marking }
  5623.                                                                                               { functions} 
  5624. theToken    A token that identifies the Apple event object specified by the objectSpecifier parameter. Your object accessor functions may need to create many tokens in order to resolve a single object specifier record; this parameter contains only the final token that identifies the requested Apple event object. If an error occurs, AEResolve returns a null descriptor record.
  5625. DESCRIPTION
  5626. The AEResolve function resolves the object specifier record passed in the objectSpecifier parameter with the help of the object accessor functions and object callback functions provided by your application. 
  5627. RESULT CODES
  5628. noErr    0    No error occurred
  5629. paramErr    –50    AEObjectInit was not called before 
  5630.          this function was called
  5631. errAEHandlerNotFound    –1717    The necessary object callback function 
  5632.         was not found (this result is returned only 
  5633.         forobject callback functions; 
  5634.             errAEAccessorNotFound [–1723] is 
  5635.         returned when an object accessor function 
  5636.             is not found)
  5637. errAEImpossibleRange    –1720    The range is not valid because it is 
  5638.         impossible for a range to include the first 
  5639.         and last objects that were specified; an 
  5640.         example is a range in which the offset of 
  5641.         the first object is greater than the offset of 
  5642.         the last object
  5643. errAEWrongNumberArgs    –1721    The number of operands provided for 
  5644.         the kAENot logical operator is not 1
  5645. errAEAccessorNotFound    –1723    There is no object accessor function for 
  5646.         the specified object class and token 
  5647.         descriptor type
  5648. errAENoSuchLogical    –1725    The logical operator in a logical 
  5649.         descriptor is not kAEAnd, kAEOr, or kAENot
  5650. errAEBadTestKey    –1726    The descriptor in a test key is neither a 
  5651.         comparison descriptor record nor a logical 
  5652.         descriptor record
  5653. errAENotAnObjectSpec    –1727    The objSpecifier parameter of 
  5654.         AEResolve is not an object specifier 
  5655.             record
  5656. errAEnegativeCount    –1729    An object-counting function returned a 
  5657.         negative result
  5658. errAEemptyListContainer    –1730    The container specified for an Apple 
  5659.         event object is an empty list
  5660. In addition to the result codes listed here, AEResolve also returns any result code returned by one of your application’s object accesssor functions or object callback functions. For example, an object accessor function can return errAENoSuchObject (–1728) when it can’t find an Apple event object, or it can return more specific result codes.
  5661. If any object accessor function or object callback function returns a result code other than noErr or errAEEventNotHandled, AEResolve immediately disposes of any existing tokens and returns. The result code it returns in this case is the result code returned by the object accessor function or the object callback function. 
  5662. SEE ALSO
  5663. For an overview of the way AEResolve works with objects accessor functions, see “Resolving Object Specifier Records,” which begins on page 2-53
  5664. Requesting User Interaction
  5665. The Apple Event Manager provides three functions that allow you to set or request user interaction levels and to initiate user interaction when your application is the server application. The AESetInteractionAllowed and AEGetInteractionAllowed functions specify the user interaction preferences for your application. Your application should call the AEInteractWithUser function before actually interacting with the user in response to an Apple event. 
  5666. 2AESetInteractionAllowed
  5667. You can use the AESetInteractionAllowed function to specify your application’s user interaction preferences for responding to an Apple event.
  5668. FUNCTION AESetInteractionAllowed 
  5669.                                         (level: AEInteractAllowed): OSErr;
  5670. level    The user interaction level to be set.
  5671. DESCRIPTION
  5672. AESetInteractionAllowed sets the user interaction level for a server application’s response to an Apple event. The level parameter must be one of three flags: kAEInteractWithSelf, kAEInteractWithLocal, or kAEInteractWithAll. 
  5673. Specifying the kAEInteractWithSelf flag allows the server application to interact with the user in response to an Apple event only when the client application and server application are the same—that is, only when the application is sending the Apple event to itself.
  5674. Specifying the kAEInteractWithLocal flag allows the server application to interact with the user in response to an Apple event only if the client application is on the same computer as the server application; this is the default if the AESetInteractionAllowed function is not used.
  5675. Specifying the kAEInteractWithAll flag allows the server application to interact with the user in response to an Apple event sent from any client application on any computer.
  5676. RESULT CODE
  5677. noErr    0    No error
  5678. 2AEGetInteractionAllowed
  5679. You can use the AEGetInteractionAllowed function to get the current user interaction preferences for responding to an Apple event.
  5680. FUNCTION AEGetInteractionAllowed 
  5681.                                 (VAR level: AEInteractAllowed): OSErr;
  5682. level    The current user interaction level, using the data type AEInteractAllowed:
  5683.     TYPE                                     AEInteractAllowed = (kAEInteractWithSelf, 
  5684.                                                                                           kAEInteractWithLocal, 
  5685.                                                                                           kAEInteractWithAll);
  5686. DESCRIPTION
  5687. The AEGetInteractionAllowed function returns a value in the level parameter that indicates the user interaction preferences for responding to an Apple event. The value returned is the interaction level set by a previous call to AESetInteractionAllowed, and consists of one of the following flags: kAEInteractWithSelf, kAEInteractWithLocal, or kAEInteractWithAll. The default value of kAEInteractWithLocal is returned if your application has not used AESetInteractionAllowed to set the interaction level explicitly.
  5688. The kAEInteractWithSelf flag indicates that the server application may interact with the user in response to an Apple event only when the client application and server application are the same—that is, only when the application is sending the Apple event to itself.
  5689. The kAEInteractWithLocal flag indicates that the server application may interact with the user in response to an Apple event only if the client application is on the same computer as the server application. This is the default if your application has not used the AESetInteractionAllowed function to set the interaction level explicitly.
  5690. The kAEInteractWithAll flag indicates that the server application may interact with the user in response to an Apple event sent from any client application on any computer.
  5691. RESULT CODE
  5692. noErr    0    No error
  5693. 2AEInteractWithUser
  5694. You can use the AEInteractWithUser function to initiate interaction with the user when your application is a server application responding to an Apple event.
  5695. FUNCTION AEInteractWithUser 
  5696.                             (timeOutInTicks: LongInt; nmReqPtr: 
  5697.                             NMRecPtr; idleProc: IdleProcPtr): OSErr;
  5698. timeOutInTicks 
  5699. The amount of time (in ticks) that your handler is willing to wait for a response from the user. You can specify a number of ticks or use one of the following constants:
  5700.     CONST kAEDefaultTimeout = -1; {value determined }
  5701.                                                       { by AEM}
  5702.       kNoTimeOut        = -2; {wait until reply }
  5703.                               { comes back}
  5704. nmReqPtr     A pointer to a Notification Manager record provided by your application. You can specify NIL for this parameter to get the default notification handling provided by the Apple Event Manager.
  5705. idleProc     A pointer to your application’s idle function, which handles events while waiting for the Apple Event Manager to return control. 
  5706. DESCRIPTION
  5707. Your application should call the AEInteractWithUser function before displaying a dialog box or alert box or otherwise interacting with the user in response to an Apple event. If the user interaction preference settings permit the application to come to the foreground, this function brings your application to the front, either directly or by posting a notification request. 
  5708. The AEInteractWithUser function checks to see if the client application set the kAENeverInteract flag for the Apple event and, if so, returns an error. If not, then the AEInteractWithUser function checks the server application’s preference set by the AESetInteractionAllowed function and compares it against the source of the Apple event—that is, whether it came from the same application, another process on the same computer, or a process running on another computer. AEInteractWithUser returns the errAENoUserInteraction result code if the user interaction preferences don’t allow user interaction. If user interaction is allowed, the Apple Event Manager brings your application to the front, either directly or by posting a notification request. If AEInteractWithUser returns the noErr result code, then your application is in the foreground and is free to interact with the user.
  5709. RESULT CODES
  5710. noErr    0    No error
  5711. errAETimeout    –1712    Apple event timed out
  5712. errAENoUserInteraction    –1713    No user interaction allowed
  5713. SEE ALSO
  5714. For a description of how to write an idle function, see “Writing an Idle Function” on page 2-150.
  5715. For examples of the use of the AEInteractWithUser function, see “Interacting With the User,” which begins on page 2-100.
  5716. Requesting More Time to Respond to Apple Events
  5717. The AEResetTimer function resets the timeout value for an Apple event to its starting value. A server application can call this function when it knows it cannot fulfill a client application’s request (either by returning a result or by sending back a reply Apple event) before the client application is due to time out.
  5718. 2AEResetTimer
  5719. You can use the AEResetTimer function to reset the timeout value for an Apple event to its starting value.
  5720. FUNCTION AEResetTimer (reply: AppleEvent): OSErr;
  5721. reply    The default reply for an Apple event, provided by the Apple Event Manager.
  5722. DESCRIPTION
  5723. When your application calls AEResetTimer, the Apple Event Manager for the server application uses the default reply to send a Reset Timer event to the client application; the Apple Event Manager for the client application intercepts this Apple event and resets the client application’s timer for the Apple event. (The Reset Timer event is never dispatched to a handler, so the client application does not need a handler for it.)
  5724. RESULT CODES
  5725. noErr    0    No error
  5726. errAEReplyNotValid    –1709    AEResetTimer was passed an invalid reply
  5727. Suspending and Resuming Apple Event Handling
  5728. The Apple Event Manager provides four functions that allow you to suspend and resume Apple event handling, specify the Apple event to be handled, and identify an Apple event that is currently being handled. The AESuspendTheCurrentEvent function allows you to suspend the processing of the Apple event that is currently being handled. The AEResumeTheCurrentEvent function informs the Apple Event Manager that your application wants to resume the handling of a previously suspended Apple event or that it has completed the handling of the Apple event. The AESetTheCurrentEvent function specifies the Apple event to be handled. The AEGetTheCurrentEvent function returns the Apple event that is currently being handled. 
  5729. 2AESuspendTheCurrentEvent
  5730. You can use the AESuspendTheCurrentEvent function to suspend the processing of the Apple event that is currently being handled. 
  5731. FUNCTION AESuspendTheCurrentEvent 
  5732.                                     (theAppleEvent: AppleEvent): OSErr;
  5733. theAppleEvent
  5734. The Apple event whose handling is to be suspended. Although the Apple Event Manager doesn’t need this parameter to identify the Apple event currently being handled, providing it is a safeguard that ensures that you are suspending the correct Apple event.
  5735. DESCRIPTION
  5736. After a server application makes a successful call to the AESuspendTheCurrentEvent function, it is no longer required to return a result or a reply for the Apple event that was being handled. It can, however, return a result if it later calls the AEResumeTheCurrentEvent function to resume event processing.
  5737. The Apple Event Manager does not automatically dispose of Apple events that have been suspended or of their default replies. (The Apple Event Manager does, however, automatically dispose of a previously suspended Apple event and its default reply if the server later resumes processing of the Apple event by calling the AEResumeTheCurrentEvent function.) If your server application does not resume processing of a suspended Apple event, it is responsible for using the AEDisposeDesc function to dispose of both the Apple event and its default reply when your application is finished with them.
  5738. RESULT CODES
  5739. noErr    0    No error
  5740. 2AEResumeTheCurrentEvent
  5741. You can use the AEResumeTheCurrentEvent function to inform the Apple Event Manager that your application wants to resume the handling of a previously suspended Apple event or that it has completed the handling of the Apple event.
  5742. FUNCTION AEResumeTheCurrentEvent 
  5743.                                     (theAppleEvent,reply: AppleEvent; 
  5744.                                      dispatcher: EventHandlerProcPtr; 
  5745.                                      handlerRefcon: LongInt): OSErr;
  5746. theAppleEvent
  5747. The Apple event whose processing is to be resumed.
  5748. reply     The default reply that is automatically provided by the Apple Event Manager for the Apple event.
  5749. dispatcher     One of the following:
  5750. n    a pointer to a routine for handling the event
  5751. n    the kAEUseStandardDispatch constant, which causes the Apple event to be dispatched the same way it was when it was first received
  5752. n    the kAENoDispatch constant, which tells the Apple Event Manager that the processing of the Apple event is complete and that it does not need to be dispatched
  5753. handlerRefcon 
  5754. If the value of the dispatcher parameter is not kAEUseStandardDispatch, this parameter is the reference constant that is passed to the handler when the handler is called. If the value of the dispatcher parameter is kAEUseStandardDispatch, the Apple Event Manager ignores the handlerRefcon parameter and instead passes the reference constant that is stored in the Apple event dispatch table entry for the Apple event. (If you want to pass the same reference constant that is stored in the Apple event dispatch table, your application can obtain the reference constant by calling the AEGetEventHandler function.)
  5755. DESCRIPTION
  5756. When your application calls the AEResumeTheCurrentEvent function, the Apple Event Manager resumes the handling of the specified Apple event using the handler specified in the dispatcher parameter; if kAENoDispatch is specified, this function simply informs the Apple Event Manager that the specified event has been handled.
  5757. RESULT CODE
  5758. noErr    0    No error
  5759. 2AESetTheCurrentEvent
  5760. You can use the AESetTheCurrentEvent function to specify the Apple event to be handled.
  5761. FUNCTION AESetTheCurrentEvent (theAppleEvent: AppleEvent): 
  5762.                                             OSErr;
  5763. theAppleEvent
  5764. The Apple eventto be handled.
  5765. DESCRIPTION
  5766. There is usually no reason for your application to use the AESetTheCurrentEvent function. Instead of calling this function, your application should let the Apple Event Manager set the current Apple event through the dispatch tables.
  5767. If you need to avoid the dispatch tables, you must use the AESetTheCurrentEvent function only in the following way:
  5768.     1.    Your application suspends handling of an Apple event by calling the AESuspendTheCurrentEvent function.
  5769.     2.    Your application calls the AESetTheCurrentEvent function to inform the Apple Event Manager that it is handling the Apple event that was suspended. It thereby makes the identity of the Apple event currently being handled available to routines that call the AEGetTheCurrentEvent function.
  5770.     3.    When your application finishes handling the Apple event, it calls the AEResumeTheCurrentEvent function with the value kAENoDispatch to tell the Apple Event Manager that the processing of the event is complete and that the Apple event does not need to be dispatched.
  5771. RESULT CODE
  5772. noErr    0    No error
  5773. 2AEGetTheCurrentEvent
  5774. You can use the AEGetTheCurrentEvent function to get the Apple event that is currently being handled. 
  5775. FUNCTION AEGetTheCurrentEvent 
  5776.                                 (VAR theAppleEvent: AppleEvent): OSErr;
  5777. theAppleEvent
  5778. The Apple event that is currently being handled; if no Apple event is currently being handled, AEGetTheCurrentEvent returns a null descriptor record in this parameter
  5779. DESCRIPTION
  5780. In many applications, the handling of an Apple event involves one or more long chains of calls to routines within the application. The AEGetTheCurrentEvent function makes it unnecessary for these calls to include the current Apple event as a parameter; the routines can simply call AEGetTheCurrentEvent to get the current Apple event when it is needed.
  5781. You can also use the AEGetTheCurrentEvent function to make sure that no Apple event is currently being handled. For example, if your application always uses an application-defined routine to delete a file, that routine can determine whether any Apple event is currently being handled by calling AEGetTheCurrentEvent, and delete the file only if AEGetTheCurrentEvent returns a null descriptor record, indicating that no Apple event is currently being handled.
  5782. RESULT CODE
  5783. noErr    0    No error
  5784. Creating Apple Events
  5785. The AECreateAppleEvent function allows you to create an Apple event. 
  5786. 2AECreateAppleEvent
  5787. You can use the AECreateAppleEvent function to create an Apple event with several important attributes but no parameters. You add parameters to the Apple event after you createit
  5788. FUNCTION AECreateAppleEvent (theAEEventClass: AEEventClass; 
  5789.                                           theAEEventID: AEEventID; target: 
  5790.                                       AEAddressDesc; returnID: Integer; 
  5791.                                           transactionID: LongInt; 
  5792.                                        VAR result: AppleEvent): OSErr;
  5793. theAEEventClass 
  5794. The event class of the Apple event to be created.
  5795. theAEEventID 
  5796. The event ID of the Apple event to be created.
  5797. target     The address of the server application. 
  5798. returnID    The return ID assigned to this Apple event; if the kAutoGenerateReturnID constant is used as the value, the Apple Event Manager assigns a return ID that is unique to the current session.
  5799. transactionID
  5800. The transaction ID for this Apple event. A transaction is a sequence of Apple events that are sent back and forth between the client and server applications, beginning with the client’s initial request for a service. All Apple events that are part of a transaction must have the same transaction ID.
  5801. result     The Apple event that the AECreateAppleEvent function creates.
  5802. DESCRIPTION
  5803. The AECreateAppleEvent function creates an Apple event.Your application is responsible for using the AEDisposeDesc function to dispose of the Apple event once you are finished with it.
  5804. If AECreateAppleEvent returns a nonzero result code, it returns a null descriptor record (a descriptor record of type typeNull, which does not contain any data) unless the Apple Event Manager is not available due to limited memory.
  5805. RESULT CODES
  5806. noErr    0    No error
  5807. memFullErr    –108    Not enough room in heap zone
  5808. SEE ALSO
  5809. See “Creating an Apple Event,” which begins on page 2-110, for more information on how to create an Apple event.
  5810. See “Specifying a Target Address” on page 2-116 for information on how to address an Apple event. 
  5811. Creating and Duplicating Descriptor Records
  5812. The AECreateDesc function takes data and converts it into a descriptor record, and the AEDuplicateDesc function makes a copy of a descriptor record.
  5813. 2AECreateDesc
  5814. You can use the AECreateDesc function to convert data into a descriptor record.
  5815. FUNCTION AECreateDesc (typeCode: DescType; dataPtr: Ptr; 
  5816.                               dataSize:             Size; VAR result: AEDesc): OSErr;
  5817. typeCode    The descriptor type for the descriptor record.
  5818. dataPtr    A pointer to the data for the descriptor record.
  5819. dataSize     The length, in bytes, of the data for the descriptor record.
  5820. result    The descriptor record that the AECreateDesc function creates. 
  5821. DESCRIPTION
  5822. The AECreateDesc function creates a new descriptor record from the specified data. Your application is responsible for using the AEDisposeDesc function to dispose of the resulting descriptor record once you are finished with it. You normally do this after receiving a result code from the AESend function.
  5823. If AECreateDesc returns a nonzero result code, it returns a null descriptor record (a descriptor record of type typeNull, which does not contain any data) unless the Apple Event Manager is not available due to limited memory.
  5824. RESULT CODES
  5825. noErr    0    No error
  5826. memFullErr    –108    Not enough room in heap zone
  5827. 2AEDuplicateDesc
  5828. You can use the AEDuplicateDesc function to make a copy of a descriptor record.
  5829. FUNCTION AEDuplicateDesc (theAEDesc: AEDesc;
  5830.                                  VAR result: AEDesc): OSErr;
  5831. theAEDesc     The descriptor record to be copied.
  5832. result    The duplicate descriptor record. 
  5833. DESCRIPTION
  5834. The AEDuplicateDesc function creates a new descriptor record by copying the descriptor record from the parameter theAEDesc. Your application is responsible for using the AEDisposeDesc function to dispose of the resulting descriptor record once you are finished with it. You normally do this after receiving a result code from the AESend function.
  5835. If AEDuplicateDesc returns a nonzero result code, it returns a null descriptor record (a descriptor record of type typeNull, which does not contain any data) unless the Apple Event Manager is not available due to limited memory.
  5836. It is common for applications to send Apple events that have one or more attributes or parameters in common. For example, if you send a series of Apple events to the same application, the address attribute is the same. In these cases, the most efficient way to create the necessary Apple events is to make a template Apple event that you can then copy—by calling the AEDuplicateDesc function—as needed. You then fill in or change the remaining parameters and attributes of the copy, send the copy by calling AESend, and dispose of the copy—by calling AEDisposeDesc—after AESend returns a result code.
  5837. RESULT CODES
  5838. noErr    0    No error
  5839. memFullErr    –108    Not enough room in heap zone
  5840. Creating Descriptor Lists and AE Records
  5841. The AECreateList function allows you to create an empty descriptor list or AE record.
  5842. 2AECreateList
  5843. You can use the AECreateList function to create an empty descriptor list or AE record.
  5844. FUNCTION AECreateList (factoringPtr: Ptr; factoredSize: Size;
  5845.                              isRecord: Boolean; 
  5846.                              VAR resultList: AEDescList): OSErr;
  5847. factoringPtr 
  5848. A pointer to the data at the beginning of each descriptor that is the same for all descriptor records in the list. If there is no common data, or if you decide not to isolate the common data, provide NIL as the value of this parameter.
  5849. factoredSize
  5850. The size of the common data. If there is no common data, or if you decide not to isolate the common data, the value of factoredSize must be 0.
  5851. isRecord     A Boolean value that specifies the kind of list to create. If you set it to TRUE, the Apple Event Manager creates an AE record. If you set it to FALSE, the Apple Event Manager creates a descriptor list.
  5852. resultList    The descriptor list or AE record that the AECreateList function creates. 
  5853. DESCRIPTION
  5854. The AECreateList function creates an empty descriptor list or AE record. Your application is responsible for using the AEDisposeDesc function to dispose of the resulting descriptor record once you are finished with it. You normally do this after receiving a result code from the AESend function.
  5855. If AECreateList returns a nonzero result code, it returns a null descriptor record (a descriptor record of type typeNull, which does not contain any data) unless the Apple Event Manager is not available due to limited memory.
  5856. RESULT CODES
  5857. noErr    0    No error
  5858. paramErr    –50    Parameter error (handler pointer is NIL or odd)
  5859. memFullErr    –108    Not enough room in heap zone
  5860. Creating Object Specifier Records
  5861. The Apple Event Manager provides five functions that you can use to create some of the components of an object specifier record or to assemble an object specifier record: 
  5862. n    The CreateOffsetDescriptor function creates an offset descriptor record, which specifies the position of an element in relation to the beginning or end of its container.
  5863. n    The CreateCompDescriptor function creates a comparison descriptor record, which specifies how to compare one or more Apple event objects with either another Apple event object or a descriptor record.
  5864. n    The CreateLogicalDescriptor function creates a logical descriptor record, which specifies a logical operator and one or more logical terms for the Apple Event Manager to evaluate.
  5865. n    The CreateRangeDescriptor function creates a range descriptor record, which specifies a series of consecutive elements in the same container.
  5866. n    The CreateObjSpecifier function assembles an object specifier record, which identifies one or more Apple event objects, from other descriptor records.
  5867. Instead of using these functions, you can create the corresponding descriptor records yourself using the AECreateDesc function, add them to an AE record using other Apple Event Manager routines, and coerce the AE record to a descriptor record of type typeObjectSpecifier. However, in most cases it is easier to use the functions listed in this section. 
  5868. All of these functions except for CreateOffsetDescriptor include a disposeInputs parameter. If this parameter is TRUE, the function automatically disposes of any descriptor records you have provided as parameters to the function. If this parameter is FALSE, ther application must dispose of the records itself. This may be more efficient for some applications because it allows allows them to keep descriptor records they can reuse.
  5869. For more information about these functions and examples of their use, see “Creating an Object Specifier Record,” which begins on page 2-118.
  5870. 2CreateOffsetDescriptor
  5871. You can use the CreateOffsetDescriptor function to create an offset descriptor record. 
  5872. FUNCTION CreateOffsetDescriptor (theOffset: LongInt; 
  5873.                                             VAR theDescriptor: AEDesc): 
  5874.                                             OSErr;
  5875. theOffset    A positive integer that specifies the offset from the beginning of the container (the first element has an offset of 1), or a negative integer that specifies the offset from the end (the last element has an offset of –1).
  5876. theDescriptor
  5877. The offset descriptor record created by CreateOffsetDescriptor.
  5878. DESCRIPTION
  5879. The CreateOffsetDescriptor function creates an offset descriptor record, which specifies the position of an element in relation to the beginning or end of its container.
  5880. RESULT CODES
  5881. noErr    0    No error occurred.
  5882. memFullErr    –108    Not enough room in heap zone
  5883. 2CreateCompDescriptor
  5884. You can use the CreateCompDescriptor function to create a comparison descriptor record.
  5885. FUNCTION CreateCompDescriptor (comparisonOperator: DescType;
  5886.                                         VAR operand1: AEDesc; 
  5887.                                         VAR operand2: AEDesc; 
  5888.                                         disposeInputs: Boolean; 
  5889.                                         VAR theDescriptor: AEDesc): 
  5890.                                         OSErr;
  5891. comparisonOperator
  5892. The comparison operator for comparing the descriptor records in the operand1 and operand2 parameters. The operator is specified by the constants listed in the description that follows.
  5893. operand1    An object specifier record.
  5894. operand2    A descriptor record (which can be an object specifier record or any other descriptor record ) whose value is to be compared to the value of operand1.
  5895. disposeInputs
  5896. If TRUE, indicates that the function is to dispose of the descriptors for the two operands.
  5897. theDescriptor
  5898. The comparison descriptor record created by CreateCompDescriptor..
  5899. DESCRIPTION
  5900. The CreateCompDescriptor function creates a comparison descriptor record, which specifies how to compare one or more Apple event objects with either another Apple event object or a descriptor record.
  5901. The actual comparison of the two operands is performed by the object comparison function provided by the client application. The way a comparison operator is interpreted is up to each application.
  5902. These are the currently defined standard comparison operators:
  5903. Constant        Meaning
  5904. kAEGreaterThan        The value of operand1 is greater than the value of 
  5905.         operand2.
  5906. kAEGreaterThanEquals        The value of operand1 is greater than or equal to 
  5907.         the value of operand2.
  5908. kAEEquals        The value of operand1 is equal to the value of 
  5909.         operand2.
  5910. kAELessThan        The value of operand1 is less than than the value of 
  5911.         operand2.
  5912. kAELessThanEquals        The value of operand1 is less than or equal to the 
  5913.         value of operand2.
  5914. kAEBeginsWith        The value of operand1 begins with the value of 
  5915.         operand2 (for example, the string "operand" begins 
  5916.         with the string "opera").
  5917. kAEEndsWith        The value of operand1 ends with the value of 
  5918.         operand2  (for example, the string "operand" ends 
  5919.         with the string "and").
  5920. kAEContains        The value of operand1 contains the value of 
  5921.         operand2  (for example, the string "operand" 
  5922.         contains the string "era").
  5923. RESULT CODES
  5924. noErr    0    No error occurred
  5925. paramErr    –50    Error in parameter list
  5926. memFullErr    –108    Not enough room in heap zone
  5927. errAECoercionFail     –1700    Data could not be coerced to the requested 
  5928.         Apple event data type
  5929. errAEWrongDataType    –1703    Wrong Apple event data type
  5930. errAENotAEDesc    –1704    Not a valid descriptor record
  5931. errAEBadListItem    –1705    Operation involving a list item failed
  5932. SEE ALSO
  5933. For an example of how to use the CreateCompDescriptor function to create a comparison descriptor record, see “Specifying a Test,” which begins on page 2-131. 
  5934. 2CreateLogicalDescriptor
  5935. You can use the CreateLogicalDescriptor function to create a logical descriptor record. 
  5936. FUNCTION CreateLogicalDescriptor (VAR logicalTerms: AEDescList; 
  5937.                                                 logicalOperator: DescType; 
  5938.                                                 disposeInputs: Boolean; 
  5939.                                                 VAR theDescriptor: AEDesc): 
  5940.                                                 OSErr;
  5941. logicalTerms
  5942. A list containing comparison descriptor records, logical descriptor records, or both. If the value of the parameter theLogicalOperator is kAEAnd or kAEOr, the list can contain any number of descriptors. If the value of the parameter theLogicalOperator is kAENot, this list must contain a single descriptor record.
  5943. logicalOperator
  5944. A logical operator represented by one of the following constants: 
  5945.     CONST                                     kAEAND             =     'AND ';
  5946.                                           kAEOR              =     'OR  ';
  5947.                                           kAENOT             =     'NOT ';
  5948. disposeInputs
  5949. If TRUE, indicates that the descriptors for the other input parameters are to be disposed of by the function.
  5950. theDescriptor
  5951.     The logical descriptor record created by CreateLogicalDescriptor.
  5952. DESCRIPTION
  5953. The CreateLogicalDescriptor function creates a logical descriptor record, which specifies a logical operator and one or more logical terms for the Apple event Manager to evaluate.
  5954. RESULT CODES
  5955. noErr    0    No error occurred
  5956. paramErr    –50    Error in parameter list
  5957. memFullErr    –108    Not enough room in heap zone
  5958. errAECoercionFail     –1700    Data could not be coerced to the requested 
  5959.         Apple event data type
  5960. errAEWrongDataType    –1703    Wrong Apple event data type
  5961. errAENotAEDesc    –1704    Not a valid descriptor record
  5962. errAEBadListItem    –1705    Operation involving a list item failed
  5963. SEE ALSO
  5964. For an example of how to use the CreateLogicalDescriptor function to create a logical descriptor record, see “Specifying a Test,” which begins on page 2-131. 
  5965. 2CreateRangeDescriptor
  5966. You can use the CreateRangeDescriptor function to create a range descriptor record. 
  5967. FUNCTION CreateRangeDescriptor (VAR rangeStart: AEDesc; 
  5968.                                             VAR rangeStop: AEDesc; 
  5969.                                             disposeInputs: Boolean; 
  5970.                                             VAR theDescriptor: AEDesc): 
  5971.                                             OSErr;
  5972. rangeStart    An object specifier record that identifies the first Apple event object in the range.
  5973. rangeStop    An object specifier record that identifies the last Apple event object in the range.
  5974. disposeInputs
  5975. If TRUE, indicates that the function will dispose of the descriptor records for the therangeStart and rangeStop parameters. If FALSE, indicates that your application must dispose of these descriptor records itself.
  5976. theDescriptor
  5977. The range descriptor record created by CreateRangeDescriptor.
  5978. DESCRIPTION
  5979. The CreateRangeDescriptor function creates a range descriptor record, which specifies a series of consecutive elements in the same container. Although the rangeStart and rangeStop parameters can be any object specifier records—including object specifier records that specify more than one Apple event object—most applications expect these parameters to specify single Apple event objects.
  5980. RESULT CODES
  5981. noErr    0    No error occurred
  5982. paramErr    –50    Error in parameter list
  5983. memFullErr    –108    Not enough room in heap zone
  5984. errAECoercionFail     –1700    Data could not be coerced to the requested 
  5985.         Apple event data type
  5986. errAEWrongDataType    –1703    Wrong Apple event data type
  5987. errAENotAEDesc    –1704    Not a valid descriptor record
  5988. errAEBadListItem    –1705    Operation involving a list item failed
  5989. SEE ALSO
  5990. For an example of how to use the CreateRangeDescriptor function to create a range descriptor record, see “Specifying a Range” on page 2-141. 
  5991. 2CreateObjSpecifier
  5992. You can use the CreateObjSpecifier function to create an object specifier record.
  5993. FUNCTION CreateObjSpecifier (desiredClass: DescType; 
  5994.                                         VAR theContainer: AEDesc; 
  5995.                                         keyForm: DescType; 
  5996.                                         VAR keyData: AEDesc; 
  5997.                                         disposeInputs: Boolean; 
  5998.                                         VAR objSpecifier: AEDesc): OSErr;
  5999. desiredClass    
  6000. The object class of the desired Apple event objects.
  6001. theContainer
  6002. The container from which to get the desired Apple event objects.
  6003. keyForm    The key form for the object specifier record.
  6004. keyData    The key data for the object specifier record.
  6005. disposeInputs
  6006. If TRUE, the descriptors for the other parameters are to be disposed of by the function.
  6007. objSpecifier
  6008. The object specifier record created by theCreateObjSpecifier function.
  6009. DESCRIPTION
  6010. The CreateObjSpecifier function assembles an object specifier record, which identifies one or more Apple event objects, from other descriptor records.
  6011. RESULT CODES
  6012. noErr    0    No error occurred
  6013. paramErr    –50    Error in parameter list
  6014. memFullErr    –108    Not enough room in heap zone
  6015. errAECoercionFail     –1700    Data could not be coerced to the requested 
  6016.         Apple event data type
  6017. errAEWrongDataType    –1703    Wrong Apple event data type
  6018. errAENotAEDesc    –1704    Not a valid descriptor record
  6019. errAEBadListItem    –1705    Operation involving a list item failed
  6020. SEE ALSO
  6021. For information about the components of an object specifier record and how to assemble them with the CreateObjSpecifier function, see “Creating an Object Specifier Record,” which begins on page 2-118.  
  6022. Adding Items to Descriptor Lists
  6023. The Apple Event Manager provides three routines that allow you to add descriptor records to any descriptor list, including an Apple event record. The AEPutPtr function takes data specified in a buffer, converts it to a descriptor record, and adds the descriptor record to a descriptor list. The AEPutDesc function adds a descriptor record to a descriptor list. The AEPutArray function puts the data for an Apple event array into a descriptor list.
  6024. 2AEPutPtr
  6025. You can use the AEPutPtr routine to add data specified in a buffer to any descriptor list as a descriptor record.
  6026. FUNCTION AEPutPtr (theAEDescList: AEDescList; index: LongInt;
  6027.                          typeCode:             DescType; dataPtr: Ptr; 
  6028.                          dataSize: Size): OSErr;
  6029. theAEDescList
  6030. The descriptor list to which to add a descriptor record.
  6031. index     The position in the descriptor list for the descriptor record. (For example, the value 2 specifies the second descriptor record in the list.) If there was already a descriptor record in the specified position, it is replaced. If the value of index is 0, the descriptor record is added to the end of the list.
  6032. typeCode    The descriptor type for the resulting descriptor record.
  6033. dataPtr     A pointer to the data for the descriptor record.
  6034. dataSize    The length, in bytes, of the data for the descriptor record.
  6035. RESULT CODES
  6036. noErr    0    No error
  6037. memFullErr    –108    Not enough room in heap zone
  6038. errAEWrongDataType    –1703    Wrong descriptor type
  6039. errAENotAEDesc    –1704    Not a valid descriptor record
  6040. errAEBadListItem    –1705    Operation involving a list item failed
  6041. errAEIllegalIndex    –1719    Not a valid list index
  6042. 2AEPutDesc
  6043. You can use the AEPutDesc function to add a descriptor record to any descriptor list.
  6044. FUNCTION AEPutDesc (theAEDescList: AEDescList; index: LongInt; 
  6045.                               theAEDesc: AEDesc): OSErr;
  6046. theAEDescList
  6047. The descriptor list to which to add a descriptor record.
  6048. index     The position in the list for the descriptor record. (For example, the value 2 specifies the second descriptor record in the list.) If there was already a descriptor record in the specified position, it is replaced. If the value of index is 0, the descriptor record is added to the end of the list.
  6049. theAEDesc     The descriptor record to be added to the list.
  6050. RESULT CODES
  6051. noErr    0    No error
  6052. memFullErr    –108    Not enough room in heap zone
  6053. errAEWrongDataType    –1703    Wrong descriptor type
  6054. errAENotAEDesc    –1704    Not a valid descriptor record
  6055. errAEBadListItem    –1705    Operation involving a list item failed
  6056. errAEIllegalIndex    –1719    Not a valid list index
  6057. 2AEPutArray
  6058. You can use the AEPutArray function to put the data for an Apple event array into any descriptor list.
  6059. FUNCTION AEPutArray (theAEDescList: AEDescList; 
  6060.                             arrayType: AEArrayType; 
  6061.                              arrayPtr: AEArrayDataPointer; 
  6062.                             itemType: DescType; 
  6063.                              itemSize: Size; itemCount: LongInt): OSErr;
  6064. theAEDescList
  6065. The descriptor list into which to put the Apple event array. If there are any items already in the descriptor list, they are replaced.
  6066. arrayType    The Apple event array type to be created. This is specified by one of the following constants: kAEDataArray, kAEPackedArray, kAEHandleArray, kAEDescArray, or kAEKeyDescArray. The kAEDataArray constant refers to an array of integers; kAEPackedArray refers to an array of characters; kAEHandleArray refers to an array of handles; kAEDescArray refers to an array of descriptor records; and kAEKeyDescArray refers to an array of keyword-specified descriptor records.
  6067. arrayPtr     A pointer to the buffer containing the array.
  6068. itemType     For packed, data, and handle arrays, the descriptor type of array items to be created.
  6069. itemSize     For packed and data arrays, the size (in bytes) of the array items to be created.
  6070. itemCount     The number of elements in the array.
  6071. DESCRIPTION
  6072. If you are putting an array into a factored descriptor list, the data for each array element must include the data that is common to all the descriptor records in the list. The Apple Event Manager automatically isolates the data you specified in the call to AECreateList that is common to all the elements of the array.
  6073. RESULT CODES
  6074. noErr    0    No error
  6075. memFullErr    –108    Not enough room in heap zone
  6076. errAEWrongDataType    –1703    Wrong descriptor type
  6077. errAENotAEDesc    –1704    Not a valid descriptor record
  6078. Adding Data and Descriptor Records to AE Records
  6079. The Apple Event Manager provides two routines that allow you to add data and keyword-specified descriptor records to AE records. The AEPutKeyPtr function takes a pointer to data, a descriptor type, and a keyword and converts them into a keyword-specified descriptor record that it adds to an AE record. The AEPutKeyDesc function takes a descriptor record and a keyword and converts them into a keyword-specified descriptor record that it adds to an AE record.  
  6080. 2AEPutKeyPtr
  6081. You can use the AEPutKeyPtr function to add a pointer to data, a descriptor type, and a keyword to an AE record as a keyword-specified descriptor record.
  6082. FUNCTION AEPutKeyPtr (theAERecord: AERecord; 
  6083.                              theAEKeyword: AEKeyword; 
  6084.                              typeCode: DescType; dataPtr: Ptr; 
  6085.                              dataSize: Size): OSErr;
  6086. theAERecord
  6087. The AE record to which to add a keyword-specified 
  6088. descriptor record.
  6089. theAEKeyword
  6090. The keyword that identifies the descriptor record. If the AE record already includes a descriptor record with this keyword, it is replaced.
  6091. typeCode     The descriptor type for the keyword-specified descriptor record.
  6092. dataPtr     A pointer to the data for the keyword-specified descriptor record.
  6093. dataSize     The length, in bytes, of the data for the keyword-specified descriptor record.
  6094. RESULT CODES
  6095. noErr    0    No error
  6096. memFullErr    –108    Not enough room in heap zone
  6097. errAEWrongDataType    –1703    Wrong descriptor type
  6098. errAENotAEDesc    –1704    Not a valid descriptor record
  6099. errAEBadListItem    –1705    Operation involving a list item failed
  6100. 2AEPutKeyDesc
  6101. You can use the AEPutKeyDesc function to add a descriptor record and a keyword to an AE record as a keyword-specified descriptor record. 
  6102. FUNCTION AEPutKeyDesc (theAERecord: AERecord; 
  6103.                               theAEKeyword: AEKeyword; 
  6104.                               theAEDesc: AEDesc): OSErr;
  6105. theAERecord 
  6106. The AE record to which to add the keyword-specified descriptor record.
  6107. theAEKeyword 
  6108. The keyword specifying the descriptor record. If there was already a keyword-specified descriptor record with this keyword, it is replaced.
  6109. theAEDesc     The descriptor record for the keyword-specified descriptor record.
  6110. RESULT CODES
  6111. noErr    0    No error
  6112. memFullErr    –108    Not enough room in heap zone
  6113. errAEWrongDataType    –1703    Wrong descriptor type
  6114. errAENotAEDesc    –1704    Not a valid descriptor record
  6115. errAEBadListItem    –1705    Operation involving a list item failed
  6116. Adding Parameters and Attributes to Apple Events
  6117. The Apple Event Manager provides four functions that allow you to add Apple event parameters and attributes to an Apple event. The AEPutParamPtr and AEPutParamDesc functions add parameters to a specified Apple event. The AEPutAttributePtr and AEPutAttributeDesc functions add attributes to a specified Apple event.
  6118. 2AEPutParamPtr
  6119. You can use the AEPutParamPtr function to add a pointer to data, a descriptor type, and a keyword to an Apple event as an Apple event parameter.
  6120. FUNCTION AEPutParamPtr (theAppleEvent: AppleEvent; 
  6121.                                 theAEKeyword: AEKeyword; 
  6122.                                 typeCode: DescType; dataPtr: Ptr; 
  6123.                                     dataSize: Size): OSErr;
  6124. theAppleEvent
  6125. The Apple event to which to add a parameter.
  6126. theAEKeyword
  6127. The keyword for the parameter to be added. If the Apple event already included a parameter with this keyword, the parameter is replaced.
  6128. typeCode    The descriptor type for the parameter.
  6129. dataPtr    A pointer to the data for the parameter.
  6130. dataSize    The length, in bytes, of the data for the parameter.
  6131. RESULT CODES
  6132. noErr    0    No error
  6133. memFullErr    –108    Not enough room in heap zone
  6134. errAEWrongDataType    –1703    Wrong descriptor type
  6135. errAENotAEDesc    –1704    Not a valid descriptor record
  6136. errAEBadListItem    –1705    Operation involving a list item failed
  6137. 2AEPutParamDesc
  6138. You can use the AEPutParamDesc function to add a descriptor record and a keyword to an Apple event as an Apple event parameter.
  6139. FUNCTION AEPutParamDesc (theAppleEvent: AppleEvent; 
  6140.                                  theAEKeyword: AEKeyword; 
  6141.                                  theAEDesc: AEDesc): OSErr;
  6142. theAppleEvent
  6143. The Apple event to which to add a parameter.
  6144. theAEKeyword
  6145. The keyword for the parameter to be added. If the Apple event already included a parameter with this keyword, the parameter is replaced.
  6146. theAEDesc     The descriptor record for the parameter.
  6147. RESULT CODES
  6148. noErr    0    No error
  6149. memFullErr    –108    Not enough room in heap zone
  6150. errAEWrongDataType    –1703    Wrong descriptor type
  6151. errAENotAEDesc    –1704    Not a valid descriptor record
  6152. errAEBadListItem    –1705    Operation involving a list item failed
  6153. 2AEPutAttributePtr
  6154. You can use the AEPutAttributePtr function to add a pointer to data, a descriptor type, and a keyword to an Apple event as an attribute.
  6155. FUNCTION AEPutAttributePtr (theAppleEvent: AppleEvent;
  6156.                                      theAEKeyword: AEKeyword; 
  6157.                                      typeCode: DescType; 
  6158.                                      dataPtr: Ptr; dataSize: Size): OSErr;
  6159. theAppleEvent 
  6160. The Apple event to which to add an attribute.
  6161. theAEKeyword
  6162. The keyword for the attribute to be added. If th Apple event already included an attribute with this keyword, the attribute is replaced. The keyword can be any of the keywords listed in the description that follows.
  6163. typeCode    The descriptor type for the attribute.
  6164. dataPtr     A pointer to the buffer containing the data to be assigned to the attribute.
  6165. dataSize    The length, in bytes, of the data to be assigned to the attribute.
  6166. DESCRIPTION
  6167. The AEPutAttributePtr function adds the specified pointer to data, descriptor type, and keyword to the specified Apple event as an attribute. The keyword can be one of the following:
  6168. Attribute keyword        Value    Description
  6169. keyAddressAttr         'addr'    Address of target application
  6170. keyEventClassAttr         'evcl'    Event class of Apple event
  6171. keyEventIDAttr        'evid'    Event ID of Apple event
  6172. keyEventSourceAttr        'esrc'    Source of the Apple event
  6173. keyInteractLevelAttr         'inte'    Settings for allowing the Apple Event
  6174.             Manager to bring a server application
  6175.             to the foreground
  6176. keyMissedKeywordAttr        'miss'    First required parameter remaining in
  6177.             an Apple event
  6178. keyOptionalKeywordAttr        'optk'    List of optional parameters
  6179.             for the Apple event
  6180. keyReturnIDAttr         'rtid'    Return ID for reply Apple event 
  6181. keyTimeoutAttr        'timo'    Length of time in ticks that the client
  6182.             will wait for a reply or a result from
  6183.             the server
  6184. keyTransactionIDAttr         'tran'    Transaction ID identifying a series of 
  6185.             Apple events
  6186. RESULT CODES
  6187. noErr    0    No error
  6188. memFullErr    –108    Not enough room in heap zone
  6189. errAECoercionFail     –1700    Data could not be coerced to the requested 
  6190.         descriptor type
  6191. errAENotAEDesc    –1704    Not a valid descriptor record
  6192. 2AEPutAttributeDesc
  6193. You can use the AEPutAttributeDesc function to add a descriptor record and a keyword to an Apple event as an attribute.
  6194. FUNCTION AEPutAttributeDesc (theAppleEvent: AppleEvent;
  6195.                                       theAEKeyword: AEKeyword; 
  6196.                                       theAEDesc: AEDesc): OSErr;
  6197. theAppleEvent
  6198. The Apple event to which you are adding an attribute.
  6199. theAEKeyword
  6200. The keyword of the attribute. If the Apple event already included an attribute with this keyword, the attribute is replaced.
  6201. theAEDesc    The descriptor record to be assigned to the attribute. The descriptor type of the specified descriptor record should match the defined descriptor type for that attribute. For example, the keyEventSourceAttr attribute has the typeShortInteger descriptor type.
  6202. DESCRIPTION
  6203. The AEPutAttributeDesc function takes a descriptor record and a keyword and adds them to an Apple event as an attribute. If the descriptor type required for the attribute is different from the descriptor type of the descriptor record, the Apple Event Manager attempts to coerce the descriptor record into the required type, with one exception: the Apple Event Manager does not attempt to coerce the data for an address attribute, thereby allowing applications to use their own address types. 
  6204. The keyword can be one of the following:
  6205. Attribute keyword        Value    Description
  6206. keyAddressAttr         'addr'    Address of target application
  6207. keyEventClassAttr         'evcl'    Event class of Apple event
  6208. keyEventIDAttr        'evid'    Event ID of Apple event
  6209. keyEventSourceAttr        'esrc'    Source of the Apple event
  6210. keyInteractLevelAttr         'inte'    Settings for allowing the Apple Event
  6211.             Manager to bring a server application
  6212.             to the foreground
  6213. keyMissedKeywordAttr        'miss'    First required parameter remaining in
  6214.             an Apple event
  6215. keyOptionalKeywordAttr        'optk'    List of optional parameters
  6216.             for the Apple event
  6217. keyReturnIDAttr         'rtid'    Return ID for reply Apple event 
  6218. keyTimeoutAttr        'timo'    Length of time in ticks that the client
  6219.             will wait for a reply or a result from
  6220.             the server
  6221. keyTransactionIDAttr         'tran'    Transaction ID identifying a series of 
  6222.             Apple events
  6223. RESULT CODES
  6224. noErr    0    No error
  6225. memFullErr    –108    Not enough room in heap zone
  6226. errAECoercionFail     –1700    Data could not be coerced to the requested 
  6227.         descriptor type
  6228. errAENotAEDesc    –1704    Not a valid descriptor record
  6229. Sending Apple Events
  6230. The AESend function allows you to send an Apple event that you have previously created with the AECreateAppleEvent function. 
  6231. 2AESend
  6232. You can use the AESend function to send an Apple event.
  6233. FUNCTION AESend (theAppleEvent: AppleEvent; 
  6234.                       VAR reply: AppleEvent; sendMode: AESendMode; 
  6235.                       sendPriority: AESendPriority; 
  6236.                        timeOutInTicks: LongInt; idleProc: IdleProcPtr; 
  6237.                        filterProc: EventFilterProcPtr): OSErr;
  6238. theAppleEvent 
  6239. The Apple event to be sent.
  6240. reply     The reply Apple event returned by the AESend function if you specify the kAEWaitReply flag in the sendMode parameter. (If you specify the kAEQueueReply flag in the sendMode parameter, you receive the reply Apple event in your event queue.) If you specify kAENoReply flag, the reply Apple event returned by this function is a null descriptor record—that is, a descriptor record of descriptor type typeNull, which does not contain data. If you specify kAEWaitReply in the sendMode parameter, your application is responsible for using the AEDisposeDesc function to dispose of the descriptor record returned in the reply parameter.
  6241. sendMode    Specifies the following: the reply mode for the Apple event (set with one of the constants kAENoReply, kAEQueueReply, or kAEWaitReply); the interaction level (set with one of the constants kAENeverInteract, kAECanInteract, or kAEAlwaysInteract, which represent flags in the keyInteractLevelAttr attribute); the application switch mode (set with the kAECanSwitchLayer constant); the reconnection mode (set with the kAEDontReconnect constant); and the return receipt mode (set with the kAEWantReceipt constant). You obtain the value for this parameter by adding the appropriate constants. (The description that follows provides more details about the sendMode flags.)
  6242. sendPriority 
  6243. Specifies whether the Apple event is put at the back of the event queue (indicated by the kAENormalPriority flag) or at the front of the queue (indicated by the kAEHighPriority flag).
  6244. timeOutInTicks 
  6245. If the reply mode specified in the sendMode parameter is kAEWaitReply, or if a return receipt is requested, this parameter specifies the length of time (in ticks) that the client application is willing to wait for the reply or return receipt from the server application before timing out. Most applications should use the kAEDefaultTimeout constant, which tells the Apple Event Manager to provide an appropriate timeout duration. If the value of this parameter is kNoTimeOut, the Apple event never times out.
  6246. idleProc     A pointer to a function for any tasks (such as displaying a wristwatch or spinning beachball cursor) that the application performs while waiting for a reply or a return receipt.
  6247. filterProc     A pointer to a routine that accepts certain incoming Apple events that are received while the handler waits for a reply or a return receipt and filters out the rest.
  6248. DESCRIPTION
  6249. You can use one of the following flags in the sendMode parameter to specify the reply mode for an Apple event. Only one of these flags may be set.
  6250. Flag        Description
  6251. kAENoReply        Your application does not want a reply Apple event; 
  6252.         the server processes your Apple event as soon as it 
  6253.         has the opportunity.
  6254. kAEQueueReply        Your application wants a reply Apple event; the reply 
  6255.         appears in your event queue as soon as the server has 
  6256.         the opportunity to process and respond to your Apple 
  6257.         event.
  6258. kAEWaitReply        Your application wants a reply Apple event and is 
  6259.         willing to give up the processor while waiting for the 
  6260.         reply; for example, if the server application is on the 
  6261.         same computer as your application, your application 
  6262.         yields the processor to allow the server to respond to 
  6263.         your Apple event.
  6264. You can communicate your user-interaction preferences to the server application by specifying one of these flags in the sendMode parameter of the AESend function. Only one of these flags may be set.
  6265. Flag        Description
  6266. kAENeverInteract        The server application should never interact with the 
  6267.         user in response to this Apple event. If this flag is set, 
  6268.         AEInteractWithUser returns the 
  6269.         errAENoUserInteraction result code. This flag is 
  6270.         the default when an Apple event is sent to a remote 
  6271.         application.
  6272. kAECanInteract        The server application can interact with the user in 
  6273.         response to this Apple event—by convention, if the 
  6274.         user needs to supply information to the server. If this 
  6275.         flag is set and the server allows interaction, 
  6276.         AEInteractWithUser either brings the server 
  6277.         application to the foreground or posts a notification 
  6278.         request. This flag is the default when an Apple event is 
  6279.         sent to a local application.
  6280. kAEAlwaysInteract        The server application can interact with the user in 
  6281.         response to this Apple event—by convention, 
  6282.         whenever the server application normally asks a user 
  6283.         to confirm a decision or interact in any other way, 
  6284.         even if no additional information is needed from 
  6285.         the user. If this flag is set     and the server allows 
  6286.         interaction, AEInteractWithUser either brings the 
  6287.         server application to the foreground or posts a 
  6288.         notification request.
  6289. The flags in the following list specify the application switch mode, the reconnection mode, and the return receipt mode. Any of these flags may be set.
  6290. Flag        Description
  6291. kAECanSwitchLayer        If both the client and server allow interaction, and if 
  6292. the client application is the active application on the local machine and is waiting for a reply (that is, it has set the kAEWaitReply flag), AEInteractWithUser brings the server directly to the foreground. Otherwise, AEInteractWithUser uses the Notification Manager to request that the user bring the server application to the foreground.
  6293. kAEDontReconnect        The Apple Event Manager must not 
  6294.         automatically try to reconnect if it receives a 
  6295.         sessClosedErr result code from the PPC Toolbox.
  6296. kAEWantReceipt        The sender wants to receive a return receipt for this 
  6297.         Apple event from the Event Manager. (Getting a 
  6298.         return receipt means only that the receiving 
  6299.         application accepted the Apple event; the Apple event 
  6300.         may or may not be handled successfully after it is 
  6301.         accepted.) If the receiving application does not send a 
  6302.         return receipt before the request times out, AESend 
  6303.         returns errAETimeout as its function result.
  6304. If the Apple Event Manager cannot find a handler for an Apple event in either the application or system Apple event dispatch table, it returns the result code errAEEventNotHandled to the server application (as the result of the AEProcessAppleEvent function). If the client application is waiting for a reply, the Apple Event Manager also returns this result code to the client.
  6305. AESend returns noErr as the function result if the Apple event was successfully sent by the Event Manager. A noErr result from AESend does not indicate that the Apple event was handled successfully; it only indicates that the Apple event was successfully sent by the Event Manager. If a result code other than noErr is returned by the handler, and if the client is waiting for a reply, it is returned in the keyErrorNumber parameter of the reply Apple event.
  6306. RESULT CODES
  6307. noErr    0    No error
  6308. memFullErr    –108    Not enough room in heap zone
  6309. connectionInvalid    –609    Connection is invalid
  6310. errAEEventNotHandled    –1708    Event wasn’t handled by an Apple event
  6311.         handler
  6312. errAEUnknownSendMode    –1710    Invalid sending mode was passed
  6313. errAEWaitCanceled    –1711    User canceled out of wait loop for reply 
  6314.         or receipt
  6315. errAETimeout    –1712    Apple event timed out
  6316. errAEUnknownAddressType    –1716    Unknown Apple event address type
  6317. SEE ALSO
  6318. For more information on sending Apple events, see “Sending an Apple Event,” which begins on page 2-143.
  6319. For information on writing an idle function, see “Writing an Idle Function” on page 2-150.
  6320. For information on writing a reply filter function, see “Writing a Reply Filter Function” on page 2-152. 
  6321. Getting the Sizes and Descriptor Types of Descriptor Records
  6322. The Apple Event Manager provides four routines that allow you to get the sizes and descriptor types of descriptor records that are not part of an Apple event record. The AESizeOfNthItem function returns the size and descriptor type of a descriptor record in a descriptor list. The AESizeOfKeyDesc function returns the size and descriptor type of a keyword-specified descriptor record in an AE record. The AESizeOfAttribute function returns the size and descriptor type of an Apple event attribute. The AESizeOfParam function returns the size and descriptor type of an Apple event parameter.
  6323. 2AESizeOfNthItem
  6324. You can use the AESizeOfNthItem function to get the size and descriptor type of a descriptor record in a descriptor list.
  6325. FUNCTION AESizeOfNthItem (theAEDescList: AEDescList; 
  6326.                                   index: LongInt; VAR typeCode: DescType; 
  6327.                                   VAR dataSize: Size): OSErr;
  6328. theAEDescList
  6329. The descriptor list containing the descriptor record.
  6330. index    The position of the descriptor record in the list (for example, 2 specifies the second descriptor record).
  6331. typeCode     The descriptor type of the descriptor record.
  6332. dataSize     Tthe length (in bytes) of the data in the descriptor record.
  6333. RESULT CODES
  6334. noErr    0    No error
  6335. errAEDescNotFound     –1701    Descriptor record was not found
  6336. errAEReplyNotArrived    –1718    Reply has not yet arrived
  6337. 2AESizeOfKeyDesc
  6338. You can use the AESizeOfKeyDesc function to get the size and descriptor type of a keyword-specified descriptor record in an AE record. 
  6339. FUNCTION AESizeOfKeyDesc (theAERecord: AERecord; 
  6340.                                   theAEKeyword: AEKeyword; 
  6341.                                   VAR typeCode: DescType; 
  6342.                                   VAR dataSize: Size): OSErr;
  6343. theAERecord
  6344. The AE record containing the desired keyword-specified descriptor record.
  6345. theAEKeyword
  6346. The keyword that specifies the desired descriptor record.
  6347. typeCode     The descriptor type of the keyword-specified descriptor record.
  6348. dataSize     The length (in bytes) of the data in the keyword-specified descriptor record.
  6349. RESULT CODES
  6350. noErr    0    No error
  6351. errAEDescNotFound     –1701    Descriptor record was not found
  6352. errAENotAEDesc    –1704    Not a valid descriptor record
  6353. errAEReplyNotArrived    –1718    Reply has not yet arrived
  6354. 2AESizeOfParam
  6355. You can use the AESizeOfParam function to get the size and descriptor type of an Apple event parameter. 
  6356. FUNCTION AESizeOfParam (theAppleEvent: AppleEvent; theAEKeyword: 
  6357.                                     AEKeyword; VAR typeCode: DescType; 
  6358.                                     VAR dataSize: Size): OSErr;
  6359. theAppleEvent
  6360. The Apple event containing the parameter.
  6361. theAEKeyword
  6362. The keyword that specifies the desired parameter.
  6363. typeCode     The descriptor type of the Apple event parameter.
  6364. dataSize     The length, in bytes, of the data in the Apple event parameter.
  6365. RESULT CODES
  6366. noErr    0    No error
  6367. errAEDescNotFound     –1701    Descriptor record was not found
  6368. errAENotAEDesc    –1704    Not a valid descriptor record
  6369. errAEReplyNotArrived    –1718    Reply has not yet arrived
  6370. 2AESizeOfAttribute
  6371. You can use the AESizeOfAttribute function to get the size and descriptor type of an Apple event attribute.
  6372. FUNCTION AESizeOfAttribute (theAppleEvent: AppleEvent; 
  6373.                                      theAEKeyword: AEKeyword; 
  6374.                                      VAR typeCode: DescType; 
  6375.                                         VAR dataSize: Size): OSErr;
  6376. theAppleEvent
  6377. The Apple event containing the desired attribute.
  6378. theAEKeyword
  6379. The keyword that specifies the attribute.
  6380. typeCode     The descriptor type of the attribute.
  6381. dataSize     The length, in bytes, of the data in the attribute.
  6382. RESULT CODES
  6383. noErr    0    No error
  6384. errAEDescNotFound     –1701    Descriptor record was not found
  6385. errAENotAEDesc    –1704    Not a valid descriptor record
  6386. errAEReplyNotArrived    –1718    Reply has not yet arrived  
  6387. Deleting Descriptor Records
  6388. The Apple Event Manager provides three functions that allow you to delete descriptor records from a descriptor list, an AE record, or an Apple event parameter. The AEDeleteItem function deletes a descriptor record from a descriptor list. The AEDeleteKeyDesc function deletes a keyword-specified descriptor record from an AE record. The AEDeleteParam function deletes an Apple event parameter. 
  6389. 2AEDeleteItem
  6390. You can use the AEDeleteItem function to delete a descriptor record from a descriptor list.
  6391. FUNCTION AEDeleteItem (theAEDescList: AEDescList; 
  6392.                               index: LongInt): OSErr;
  6393. theAEDescList
  6394. The descriptor list containing the descriptor record to be deleted.
  6395. index    The position of the descriptor record to delete (for example, 2 specifies the second item).
  6396. RESULT CODES
  6397. noErr    0    No error
  6398. errAEDescNotFound     –1701    Descriptor record was not found
  6399. errAENotAEDesc    –1704    Not a valid descriptor record
  6400. errAEBadListItem    –1705    Operation involving a list item failed
  6401. 2AEDeleteKeyDesc
  6402. You can use the AEDeleteKeyDesc function to delete a keyword-specified descriptor record from an AE record.
  6403. FUNCTION AEDeleteKeyDesc (theAERecord: AERecord; 
  6404.                                  theAEKeyword: AEKeyword): OSErr;
  6405. theAERecord
  6406. The AE record containing the keyword-specified descriptor record to be deleted.
  6407. theAEKeyword
  6408. The keyword that specifies the descriptor record to be deleted.
  6409. RESULT CODES
  6410. noErr    0    No error
  6411. errAEDescNotFound     –1701    Descriptor record was not found
  6412. errAENotAEDesc    –1704    Not a valid descriptor record
  6413. badListItem    –1705    Operation involving a list item failed
  6414. 2AEDeleteParam
  6415. You can use the AEDeleteParam function to delete an Apple event parameter.
  6416. FUNCTION AEDeleteParam (theAppleEvent: AppleEvent; 
  6417.                                 theAEKeyword: AEKeyword): OSErr;
  6418. theAppleEvent
  6419. The Apple event containing the parameter to be deleted.
  6420. theAEKeyword
  6421. The keyword that specifies the parameter to be deleted.
  6422. RESULT CODES
  6423. noErr    0    No error
  6424. errAEDescNotFound     –1701    Descriptor record was not found
  6425. errAENotAEDesc    –1704    Not a valid descriptor record
  6426. errAEBadListItem    –1705    Operation involving a list item
  6427.         failed
  6428. Deallocating Memory for Descriptor Records
  6429. The AEDisposeDesc function deallocates the memory used by a descriptor record. Because all Apple event structures (except for keyword-specified descriptor records) are descriptor records, you can use AEDisposeDesc for any of them.
  6430. 2AEDisposeDesc
  6431. You can use the AEDisposeDesc function to deallocate the memory used by a descriptor record. 
  6432. FUNCTION AEDisposeDesc (VAR theAEDesc: AEDesc): OSErr;
  6433. theAEDesc     The descriptor record to deallocate.
  6434. RESULT CODE
  6435. noErr    0    No error
  6436. Deallocating Memory for Tokens
  6437. Whenever the AEResolve function returns a token to your event handler as the final result of the resolution of an object specifier record passed to AEResolve, your application should call the AEDisposeToken function to deallocate the memory used by the token.
  6438. 2AEDisposeToken
  6439. You can use the AEDisposeToken function to  deallocate the memory used by a token.
  6440. FUNCTION AEDisposeToken (VAR theToken: AEDesc): OSErr;
  6441. theToken    The token to be disposed of.
  6442. DESCRIPTION
  6443. When your application calls the AEDisposeToken function, the Apple Event Manager first calls your application’s token disposal function (the MyDisposeToken function described on page 2-260) if you haveprovided one. If you haven’t provided a token disposal function, or if your application’s token disposal function returns errAEEventNotHandled as the function result, the Apple Event Manager calls the system token disposal function if one is available. If there is no system token disposal function or the function returns errAEEventNotHandled as the function result, the Apple Event Manager calls the AEDisposeDesc function to dispose of the token.
  6444. RESULT CODES
  6445. noErr    0    No error occurred
  6446. paramErr    –50    AEObjectInit was not called before this 
  6447.         function was called
  6448. notASpecialFunction    –1714    Wrong keyword for a special function
  6449. In addition to these result codes, AEDisposeToken also returns result codes returned by the token disposal function that disposed of the token.
  6450. Coercing Descriptor Types
  6451. The Apple Event Manager provides two functions that allow you to coerce descriptor types. The AECoercePtr function takes a pointer to data and a desired descriptor type and attempts to coerce the data into the desired descriptor type. The AECoerceDesc function attempts to coerce the data in a descriptor record to another descriptor type.
  6452. 2AECoercePtr
  6453. You can use the AECoercePtr function to coerce data into a desired descriptor type. If successful, it creates a descriptor record containing the newly coerced data. 
  6454. FUNCTION AECoercePtr (typeCode: DescType; dataPtr: Ptr; 
  6455.                              dataSize: Size;                     toType: DescType; 
  6456.                              VAR result: AEDesc): OSErr;
  6457. typeCode     The descriptor type of the source data.
  6458. dataPtr     A pointer to the data to be coerced.
  6459. dataSize     The length, in bytes, of the data to be coerced.
  6460. toType    The desired descriptor type of the resulting descriptor record.
  6461. result    The resulting descriptor record. 
  6462. DESCRIPTION
  6463. This function creates a new descriptor record by coercing the specified data. Your application is responsible for using the AEDisposeDesc function to dispose of the resulting descriptor record once you are finished using it.
  6464. If AECoercePtr returns a nonzero result code, it returns a null descriptor record (a descriptor record of type typeNull, which does not contain any data) unless the Apple Event Manager is not available due to limited memory.
  6465. RESULT CODES
  6466. noErr    0    No error
  6467. memFullErr    –108    Not enough room in heap zone
  6468. errAECoercionFail     –1700    Data could not be coerced to the requested 
  6469.         descriptor type
  6470. 2AECoerceDesc
  6471. You can use the AECoerceDesc function to coerce the data in a descriptor record to another descriptor type. 
  6472. FUNCTION AECoerceDesc (theAEDesc: AEDesc; toType: DescType; 
  6473.                               VAR result:             AEDesc): OSErr;
  6474. theAEDesc    The descriptor record whose data is to be coerced.
  6475. toType    The desired descriptor type of the resulting descriptor record.
  6476. result    The resulting descriptor record.
  6477. DESCRIPTION
  6478. The AECoerceDesc function creates a new descriptor record by coercing the specified descriptor record. Your application is responsible for using the AEDisposeDesc function to dispose of the resulting descriptor record once you are finished using it.
  6479. If AECoerceDesc returns a nonzero result code, it returns a null descriptor record (a descriptor record of type typeNull, which does not contain any data) unless the Apple Event Manager is not available due to limited memory.
  6480. RESULT CODES
  6481. noErr    0    No error
  6482. memFullErr    –108    Not enough room in heap zone
  6483. errAECoercionFail     –1700    Data could not be coerced to the requested 
  6484.         descriptor type
  6485. Creating and Managing the Coercion Handler Dispatch Tables
  6486. The Apple Event Manager provides three functions that allow you to create and manage the coercion handler dispatch tables. The AEInstallCoercionHandler function installs a coercion handler routine in either the application or system coercion dispatch table. The AEGetCoercionHandler function returns the handler for a specified descriptor type coercion. The AERemoveCoercionHandler function removes a coercion handler from either the application or system coercion table.
  6487. 2AEInstallCoercionHandler
  6488. You can use the AEInstallCoercionHandler function to install a coercion handler routine in either the application or system coercion handler dispatch table.
  6489. FUNCTION AEInstallCoercionHandler (fromType: DescType; 
  6490.                                               toType: DescType; 
  6491.                                                    handler: ProcPtr; 
  6492.                                               handlerRefcon: LongInt; 
  6493.                                                   fromTypeIsDesc: Boolean; 
  6494.                                                   isSysHandler: Boolean): OSErr;
  6495. fromType     The descriptor type of the data coerced by the handler.
  6496. toType     The descriptor type of the resulting data. If there was already an entry in the specified coercion handler table for the same source descriptor type and result descriptor type, it is replaced.
  6497. handler     A pointer to the coercion handler. Note that a handler in the system coercion table must reside in the system heap; this means that if the value of the isSysHandler parameter is TRUE, the handler parameter should point to a location in the system heap. Otherwise, if you put your system handler code in your application heap, you must remove the handler when your application quits by using the AERemoveCoercionHandler function.
  6498. handlerRefcon 
  6499. A reference constant that is passed by the Apple Event Manager to the handler each time the handler is called. If your handler doesn’t expect a reference constant, use 0 as the value of this parameter.
  6500. fromTypeIsDesc 
  6501. Specifies the form of the data to be coerced. If the value of this parameter is TRUE, the coercion handler expects the data to be passed as a descriptor record. If the value is FALSE, the coercion handler expects a pointer to the data to be coerced. Because it is more efficient for the Apple Event Manager to provide a pointer to data than to a descriptor record, all coercion routines should accept a pointer to data if possible.
  6502. isSysHandler     
  6503. Specifies the coercion table to which to add the handler. If the value of this parameter is TRUE, the handler is added to the system coercion table and made available to all applications. If the value is FALSE, the handler is added to the application coercion table. Note that a handler in the system coercion table must reside in the system heap; this means that if the value of the isSysHandler parameter is TRUE, the handler parameter must point to a location in the system heap.
  6504. DESCRIPTION
  6505. Before using AEInstallCoercionHandler to install a handler for a particular descriptor type into the system coercion handler dispatch table, use the AEGetCoercionHandler function to determine whether the table already contains a coercion handler for that descriptor type. If an entry exists, AEGetCoercionHandler returns a reference constant and a pointer to that handler. Chain these to your coercion handler by providing pointers to the previous handler and its reference constant in the handlerRefcon parameter of AEInstallCoercionHandler. If your coercion handler returns the error errAECoercionFail, use these pointers to call the previous handler. If you remove your system coercion handler, be sure to reinstall the chained handlers.
  6506. When an application calls a system coercion handler, the A5 register is set up for the calling application. For this reason, if you provide a system coercion handler, it should never use A5 global variables or anything that depends on a particular context; otherwise, the application that calls the system handler may crash.<36pt\>\x12 <8bat\>u
  6507. RESULT CODES
  6508. noErr    0    No error
  6509. memFullErr    –108    Not enough room in heap zone
  6510. 2AEGetCoercionHandler
  6511. You can use the AEGetCoercionHandler function to get the handler for a specified descriptor type coercion.
  6512. FUNCTION AEGetCoercionHandler (fromType: DescType; 
  6513.                                          toType: DescType; 
  6514.                                           VAR handler: ProcPtr; 
  6515.                                          VAR handlerRefcon: LongInt; 
  6516.                                           VAR fromTypeIsDesc: Boolean; 
  6517.                                           isSysHandler: Boolean): OSErr;
  6518. fromType    The descriptor type of the data coerced by the handler
  6519. toType     The descriptor type of the resulting data.
  6520. handler     A pointer to the desired coercion handler.
  6521. handlerRefcon 
  6522. The reference constant for the desired handler. The Apple Event Manager passes this reference constant to the handler each time the handler is called.
  6523. fromTypeIsDesc 
  6524. If the AEGetCoercionHandler function returns TRUE in this parameter, the coercion handler expects the data to be passed as a descriptor record. If the function returns FALSE, the coercion handler expects a pointer to the data.
  6525. isSysHandler 
  6526. Specifies the coercion table from which to get the handler. If the value of this parameter is TRUE, the handler is taken from the system coercion table. If the value is FALSE, the handler is taken from the application coercion table.
  6527. RESULT CODES
  6528. noErr    0    No error
  6529. memFullErr    –108    Not enough room in heap zone
  6530. errAEHandlerNotFound    –1717    No coercion handler found
  6531. 2AERemoveCoercionHandler
  6532. You can use the AERemoveCoercionHandler function to remove a coercion handler from either the application or system coercion handler dispatch table.
  6533. FUNCTION AERemoveCoercionHandler (fromType: DescType; 
  6534.                                             toType: DescType; 
  6535.                                                 handler: ProcPtr; 
  6536.                                             isSysHandler: Boolean): OSErr;
  6537. fromType     The descriptor type of the data coerced by the handler.
  6538. toType     The descriptor type of the resulting data.
  6539. handler    A pointer to the coercion handler. Although the fromType and toType parameters would be sufficient to identify the handler to be removed, providing the handler parameter is a safeguard to ensure that you remove the correct handler.
  6540. isSysHandler 
  6541. The coercion table from which to remove the handler. If the value of this parameter is TRUE, the handler is removed from the system coercion table. If the value is FALSE, the handler is removed from the application coercion dispatch table.
  6542. RESULT CODES
  6543. noErr    0    No error
  6544. memFullErr    –108    Not enough room in heap zone
  6545. errAEHandlerNotFound    –1717    No coercion handler found
  6546. Creating and Managing the Special Handler Dispatch Tables
  6547. The Apple Event Manager provides three functions that allow you to create and manage the special handler dispatch tables. The AEInstallSpecialHandler function installs an entry for a special handler in either the application or system special handler dispatch table. The AEGetSpecialHandler function returns the handler for a specified special handler. The AERemoveSpecialHandler function removes a special handler from either the application or system special handler dispatch table. 
  6548. You can also use the AEInstallSpecialHandler, AEGetSpecialHandler, and AERemoveSpecialHandler functions to install, get, and remove object callback functions—including system object callback functions, which cannot be installed with the AESetObjectCallback function. When using any of these functions to install, get, or remove object callback functions, use one of the following constants as the value of the functionClass parameter to specify the object callback function:
  6549. Object callback function        Constant
  6550. Object-counting function        keyAECountProc
  6551. Object comparison function        keyAECompareProc
  6552. Token disposal function        keyDiposeTokenProc
  6553. Error callback function        keyAEGetErrDescProc
  6554. Mark token function        keyAEMarkTokenProc
  6555. Object-marking function        keyAEMarkProc
  6556. Mark-adjusting function        keyAEAdjustMarksProc
  6557. You can also use the AERemoveSpecialHandler function to disable all the Apple Event Manager routines that support Apple event objects. To do this, specify the constant keySelectProc in the functionClass parameter as described on page 2-253. 
  6558. 2AEInstallSpecialHandler
  6559. You can use the AEInstallSpecialHandler function to install a special handler  in either the application or system special handler dispatch table.
  6560. FUNCTION AEInstallSpecialHandler (functionClass: AEKeyword; 
  6561.                                              handler: ProcPtr; 
  6562.                                              isSysHandler: Boolean): OSErr;
  6563. functionClass 
  6564. The keyword for the special handler that isinstalled. There is currently only one value allowed for this parameter: the keyPreDispatch constant, which identifies a handler routine that is called immediately before the Apple Event Manager dispatches an Apple event. If there was already an entry in the specified special handler dispatch table for the same value of functionClass, it is replaced.
  6565. handler     A pointer to the special handler. Note that a handler in the system special handler dispatch table must reside in the system heap; this means that if the value of the isSysHandler parameter is TRUE, the handler parameter should point to a location in the system heap. Otherwise, if you put your system handler code in your application heap, you must remove the handler when your application quits by using the AERemoveSpecialHandler function.
  6566. isSysHandler 
  6567. The special handler dispatch table to which to add the handler. If the value of this parameter is TRUE, the handler is added to the system handler dispatch table and made available to all applications. If the value is FALSE, the handler is added to the application handler table.
  6568. When an application calls a system special handler, the A5 register is set up for the calling application. For this reason, if you provide a system special handler, it should never use A5 global variables or anything that depends on a particular context; otherwise, the application that calls the system handler may crash.<36pt\>\x12 <8bat\>u
  6569. RESULT CODES
  6570. noErr    0    No error
  6571. paramErr    –50    Parameter error (handler pointer is NIL or
  6572.             odd)
  6573. memFullErr    –108    Not enough room in heap zone
  6574. errAENotASpecialFunction    –1714    Wrong keyword for a special function
  6575. 2AEGetSpecialHandler
  6576. You can use the AEGetSpecialHandler function to get a specified special handler.
  6577. FUNCTION AEGetSpecialHandler (functionClass: AEKeyword; 
  6578.                                         VAR handler: ProcPtr; 
  6579.                                         isSysHandler: Boolean): OSErr;
  6580. functionClass 
  6581. The keyword that specifies the desired special handler. There is currently only one value allowed for this parameter: the keyPreDispatch constant, which identifies a handler routine that is called immediately before the Apple Event Manager dispatches an Apple event. 
  6582. handler     A pointer to the special handler.
  6583. isSysHandler
  6584. Specifies the special handler dispatch table from which to get the handler. If the value of this parameter is TRUE, the handler is taken from the system special handler dispatch table. If the value is FALSE, the handler is taken from the application special handler dispatch table.
  6585. RESULT CODES
  6586. noErr    0    No error
  6587. memFullErr    –108    Not enough room in heap zone
  6588. errAENotASpecialFunction    –1714    Wrong keyword for a special handler
  6589. 2AERemoveSpecialHandler
  6590. You can use the AERemoveSpecialHandler function to remove a handler from a special handler table.
  6591. FUNCTION AERemoveSpecialHandler (functionClass: AEKeyword; 
  6592.                                             handler: ProcPtr; 
  6593.                                             isSysHandler: Boolean): OSErr;
  6594. functionClass 
  6595. The keyword for the special handler to be removed. There are currently two values allowed for the functionClass parameter: keyPreDispatch and keySelectProc. The keyPreDispatch constant identifies a handler that is called immediately before the Apple Event Manager dispatches an Apple event. The keySelectProc constant indicates that you want to disable the Object Support Library —that is, all the routines that support Apple event objects (see the description that follows for more information about how to do this)
  6596. handler     A pointer to the special handler to be removed. Although the functionClass parameter would be sufficient to identify the handler to be removed, providing the handler parameter is a safeguard to ensure that you remove the correct handler.
  6597. isSysHandler 
  6598. Specifies the special handler dispatch table from which to remove the handler. If the value of this parameter is TRUE, the handler is taken from the system special handler dispatch table. If the value is FALSE, the handler is removed from the application special handler dispatch table.
  6599. DESCRIPTION
  6600. In addition to using the AERemoveSpecialHandler function to remove specific special handlers, you can use the function to disable all Apple Event Manager routines that support Apple event objects—that is, all the routines available to your application as a result of linking the Object Support Library (OSL) and calling the AEObjectInit function. 
  6601. An application that expects its copy of the OSL to move after it is installed—for example, an application that keeps it in a stand-alone code resource—would need to do this. When an application calls AEObjectInit to initialize the OSL, the OSL installs the addresses of its routines as extensions to the pack.  If those routines move, the addresses become invalid.
  6602. In order to disable the OSL, you should pass the keyword keySelectProc in the functionClass parameter, NIL in the handler parameter, and FALSE in the isSysHandler parameter. Once you have called  the AERemoveSpecialHandler function with these parameters, subsequent calls to any of the Apple Event Manager routines that support Apple event objects will return errors. To initialize the OSL after disabling it with the AERemoveSpecialHandler function, your application must call AEObjectInit again.
  6603. If you expect to initialize the Object Support library and disable it several times, you should remove your application’s object accessor functions from your application’s object accessor dispatch table using the AERemoveObjectAccessor function before you call AERemoveSpecialHandler. 
  6604. RESULT CODES
  6605. noErr    0    No error
  6606. memFullErr    –108    Not enough room in heap zone
  6607. errAENotASpecialFunction    –1714    Wrong keyword for a special function
  6608. Application-Defined Functions
  6609. The AEResolve function performs tasks that are required to resolve any object specifier record, such as parsing its contents, keeping track of the results of tests, and handling memory management. When necessary, AEResolve calls application-defined functions to perform tasks that are unique to the application, such as locating a specific Apple event object in the application’s data structures or counting the number of Apple event objects in a container. 
  6610. AEResolve can call two kinds of application-defined functions:
  6611. n    Object accessor functions locate Apple event objects. Every application that supports simple object specifier records must provide one or more object accessor functions. 
  6612. n    Object callback functions perform other tasks that only an application can perform, such as counting, comparing, or marking Apple event objects. You can provide up to seven object callback functions, depending on the needs of your application.
  6613. This section provides model declarations for the object accessor functions and object callback functions that your application can provide.
  6614. Object Accessor Functions
  6615. You must provide one or more object accessor functions that can locate all the element classes and properties listed in the Apple Event Registry: Standard Suites for the object classes supported by your application. This section provides a declaration for the object accessor functions that your application can provide.
  6616. 2MyObjectAccessor
  6617. Object accessor functions locate Apple event objects of a specified object class in a container identified by a token of a specified descriptor type. 
  6618. FUNCTION MyObjectAccessor (desiredClass: DescType; 
  6619.                                     containerToken: AEDesc; 
  6620.                                     containerClass: DescType; 
  6621.                                     keyForm: DescType; keyData: AEDesc; 
  6622.                                     VAR theToken: AEDesc; 
  6623.                                     theRefcon: LongInt): OSErr;
  6624. desiredClass
  6625. The object class of the desired Apple event object or objects.
  6626. containerToken
  6627. A token that specifies the container of the desired Apple event object or objects.
  6628. containerClass
  6629. The object class of the container.
  6630. keyForm    The key form specified by the object specifier record being resolved.
  6631. keyData    The key data specified by the object specifier record being resolved..
  6632. theRefcon    A reference constant that the Apple Event Manager passes to the object accessor function each time it is called.
  6633. theToken    The token returned by the MyObjectAccessor function.
  6634. DESCRIPTION
  6635. Each object accessor function provided by your application should either find elements of a specified object class or find properties of an Apple event object. The AEResolve function uses the object class ID of the specified Apple event object and the descriptor type of the token that identifiesthe object’s container to determine which object accessor function to call. To install an object accessor function either in your application’s object accessor dispatch table or in the system object accessor dispatch table, use the AEInstallObjectAccessor function, which is described on page 2-189. 
  6636. RESULT CODES
  6637. noErr    0    No error occurred.
  6638. errAEEventNotHandled    –1708    The object accessor function is unable to 
  6639.         locate the requested Apple event object or 
  6640.         objects; if the Apple Event Manager receives 
  6641.         this result, it attempts to use other methods of 
  6642.         locating them, such as calling an equivalent 
  6643.         system object accessor function
  6644. SEE ALSO
  6645. For information about installing object accessor functions, see “Installing Entries in the Object Accessor Dispatch Tables,” which begins on page 2-66.
  6646. For information about writing object accessor functions, see “Writing Object Accessor Functions,” which begins on page 2-157. 
  6647. Object Callback Functions
  6648. If an Apple event parameter consists of an object specifier record, your handler for the Apple event typically calls AEResolve to begin the process of locating the requested Apple event object or objects. AEResolve in turn calls object accessor functions and, if necessary, object callback functions provided by your application when it needs the information they can provide.
  6649. This section provides declarations for the seven object callback functions that your application can provide:
  6650. n    The object-counting function (MyCountObjects) counts the number of elements of a specified class in a specified container, so that the Apple Event Manager can determine how many elements it must examine to find the element or elements that pass a test. Your application must provide one object-counting function if it supports complete object specifier records.  
  6651. n    The object comparison function (MyCompareObjects) compares one element to another element or to a descriptor record. Your application must provide one object compoarison function if it supports complete object specifier records. 
  6652. n    The token disposal function (MyDisposeToken) disposes of a token after either the Apple Event Manager or your application calls the AEDisposeToken function. If no token disposal function is available, the Apple Event Manager uses the AEDisposeDesc function instead. Your application must provide one token disposal function if it supports object marking or if disposing of some of its tokens requires more than a call to AEDisposeDesc.
  6653. n    The error callback function (MyGetErrorDesc) gives the Apple Event Manager an address to which to write the descriptor record it is currently working with if an error occurs while AEResolve is attempting to resolve an object specifier record. Your application is not required to provide an error callback function. 
  6654. n    The mark token function (MyGetMarkToken) gets a mark token that identifies the way your application marks Apple event objects during the current session while resolving a single object specifier record that specifies a test. Your application must provide this function if it supports marking.
  6655. n    The object-marking function (MyMark) marks a specified Apple event object. Your application must provide this function if it supports marking.
  6656. n    The mark-adjusting function (MyAdjustMarks) adjusts the marks made with the current mark token. Your application must provide this function if it supports marking.
  6657. For information about writing and installing object callback functions, see “Writing Object Callback Functions,” which begins on page 2-173.
  6658. 2 MyCountObjects
  6659. If your application supports complete object specifier records, you must provide one object-counting function. An object-counting function counts the number of Apple event objects of a specified class in a specified container. 
  6660. FUNCTION MyCountObjects (desiredClass: DescType; 
  6661.                                 containerClass: DescType; 
  6662.                                 theContainer: AEDesc; 
  6663.                                 VAR result: LongInt): OSErr;
  6664. desiredClass
  6665.     The object class of the Apple event objects to be counted.
  6666. containerClass
  6667.     The object class of the container for the Apple event objects to be counted
  6668. containerToken
  6669.     A token that identifies the container for the Apple event objects to be counted.
  6670. result    The number of Apple objects of the specified class that the MyCountObjects counted in the specified container.
  6671. DESCRIPTION
  6672. The Apple Event Manager calls your object-counting function whenever it is resolving an object specifier record and, in order to perform a test, requires a count of the number of Apple event objects of a given class in a given container.
  6673. RESULT CODES
  6674. noErr    0    No error occurred.
  6675. errAEEventNotHandled    –1708    The object-counting function is unable to 
  6676.         count the specified Apple event objects; if 
  6677.         the Apple Event Manager receives this result, 
  6678.         it attempts to use other methods of counting 
  6679.         the Apple event objects, such as calling an 
  6680.             equivalent system object-counting function
  6681. SEE ALSO
  6682. For more information, see “Writing an Object-Counting Function” on page 2-175. 
  6683. 2MyCompareObjects
  6684. If your application supports complete object specifier records, you must provide one object comparison function. An object comparison function compares one Apple event object to another Apple event object or to a descriptor record and returns TRUE or FALSE. 
  6685. FUNCTION MyCompareObjects (comparisonOperator: DescType; 
  6686.                                     object: AEDesc; 
  6687.                                     objectOrDescToCompare: AEDesc; 
  6688.                                     VAR result: Boolean): OSErr;
  6689. comparisonOperator
  6690. The comparison operator. The current version of the Apple Event Registry: Standard Suites lists all the constants for comparison operators. Constants for standard comparison operators listed at the time of publication of this book are also summarized in the description that follows.
  6691. object    An object specifier record.
  6692. objectOrDescToCompare
  6693. An object specifier record or some other descriptor record that specifies either an Apple event object or a value to compare to the Apple event object specified by the object parameter.
  6694. result    If TRUE, the values of theobject and objectOrDescToCompare parameters have the relationship specified by the comparisonOperator parameter; if FALSE, they do not.
  6695. DESCRIPTION
  6696. The Apple Event Manager calls your object comparison function whenever it is resolving an object specifier record and, in order to perform a test, needs to compare an Apple event object with another Apple event object or with a value.
  6697. It is up to your application to interpret the comparison operators it receives. The meaning of comparison operators differs depending on the Apple event objects being compared, and not all comparison operators apply to all object classes. 
  6698. The following are the standard comparison operators defined in the Apple Event Registry: Standard Suites at the time this book is published. Future versions of the Apple Event Registry may include additional comparison operators.
  6699. Constant        Meaning
  6700. kAEGreaterThan        The value of the first operand is greater than the 
  6701.         value of the second operand.
  6702. kAEGreaterThanEquals        The value of the first operand is greater than or equal 
  6703.         to the value of the second operand.
  6704. kAEEquals        The value of the first operand is equal to the value of 
  6705.         the second operand.
  6706. kAELessThan        The value of the first operand is less than the 
  6707.         value of the second operand.
  6708. kAELessThanEquals        The value of the first operand is less than or equal to 
  6709.         the value of the second operand.
  6710. kAEBeginsWith        The value of the first operand begins with the value 
  6711.         of the second operand (for example, the string 
  6712.         "operand" begins with the string "opera").
  6713. kAEEndsWith        The value of the first operand ends with the value of 
  6714.         the second operand  (for example, the string 
  6715.         "operand" ends with the string "and").
  6716. kAEContains        The value of the first operand contains the value of 
  6717.         the second operand  (for example, the string 
  6718.         "operand" contains the string "era").
  6719. RESULT CODES
  6720. noErr    0    No error occurred
  6721. errAEEventNotHandled    –1708    The object comparison function is unable 
  6722.         to compare the specified Apple event 
  6723.         objects; if the Apple Event Manager gets 
  6724.         this result, it attempts to use other methods 
  6725.         of comparison, such as calling an 
  6726.         equivalent system object comparison 
  6727.         function
  6728. SEE ALSO
  6729. For more information, see “Writing an Object Comparison Function” on page 2-177.
  6730. 2MyDisposeToken
  6731. If your application requires more than a call to the AEDisposeDesc function to dispose of a token, or if it supports marking callback functions, you must provide one token disposal function. A token disposal function disposes of a specified token. 
  6732. FUNCTION MyDisposeToken (VAR unneededToken: AEDesc): OSErr;
  6733. unneededToken
  6734. The token to dispose of.
  6735. DESCRIPTION
  6736. The Apple Event Manager calls your token disposal function whenever it needs to dispose of a token. It also calls your disposal function when your application calls the AEDisposeToken function. If your application does not provide a token disposal function, the Apple Event Manager calls AEDisposeDesc instead.
  6737. Your token disposal function must be able to dispose of all of the token types used by your application. 
  6738. If your application supports marking, a call to MyDisposeToken to dispose of a mark token lets you know that your can unmark the objects marked with that mark token. 
  6739. RESULT CODES
  6740. noErr    0    No error occurred.
  6741. errAEEventNotHandled    –1708    The token disposal function is unable to 
  6742.         dispose of the token; if the Apple Event 
  6743.         Manager gets this result from an 
  6744.         application’s token disposal routine, it looks
  6745.         for a system token disposal function if one is 
  6746.         available; if this also fails, it calls the 
  6747.         AEDisposeDesc function to dispose of the 
  6748.         token
  6749. 2MyGetErrorDesc
  6750. If you want to find out which descriptor record is responsible for an error that occurs during a call to the AEResolve function, you can provide an error callback function. An error callback function returns a pointer to an address at which the Apple Event Manager can store the descriptor record it is currently working with if an error occurs during a call to AEResolve.
  6751. FUNCTION MyGetErrorDesc (VAR errDescPtr: DescPtr): OSErr;
  6752. errDescPtr    A pointer to an address.
  6753. DESCRIPTION
  6754. Shortly after your application calls AEResolve, the Apple Event Manager calls the MyGetErrorDesc function and writes a null descriptor record to the address returned. If an error occurs during the resolution of the object specifier record, the Apple Event Manager calls the MyGetError function again and writes the descriptor record—often an object specifier record—to the address returned.
  6755. Normally you should maintain a single global variable of type AEDesc whose address your MyGetErrorDesc function returns no matter how many times it is called. Be careful if you use any other method. When recovering from an error, the Apple Event Manager never writes to the address you provide unless it already contains a null descriptor record. Thus, if you don’t maintain a single global variable as just described, you should write null descriptor records to any addresses passed by your MyGetErrorDesc function that are different from the address returned the first time your function was called after a given call to AEResolve.
  6756. If the result code returned by the MyGetErrorDesc function has a nonzero value, the Apple Event Manager continues to resolve the object specifier record as if it had never called the error callback function.
  6757. RESULT CODES
  6758. noErr    0    No error occurred 
  6759. 2MyGetMarkToken
  6760. If your application supports marking, you must provide one mark token function. A mark token function returns a mark token. 
  6761. FUNCTION MyGetMarkToken (containerToken: AEDesc; 
  6762.                                 containerClass: DescType; 
  6763.                                 VAR result: AEDesc): OSErr;
  6764. containerToken
  6765. The Apple event object that contains the elements to be marked with the mark token.
  6766. containerClass
  6767. The object class of the container that contains the objects to be marked.
  6768. result    The mark token returned by MyGetMarkToken.
  6769. DESCRIPTION
  6770. The Apple Event Manager calls the MyGetMarkToken function provided by your application in order to get a mark token. Like other tokens, the mark token returned can be a descriptor record of any type; however, unlike other tokens, a mark token identifies the way your application will mark Apple event objects during the current session while resolving a single object specifier record that specifies the key form formTest. 
  6771. A mark token is valid until the Apple Event Manager either disposes of it (by calling AEDisposeToken) or returns it as the result of the AEResolve function. If the final result of a call to AEResolve is a mark token, the Apple event objects currently marked for that mark token are those specified by the object specifier record passed to AEResolve, and your application can proceed to do whatever the Apple event has requested. Note that your application is responsible for disposing of a final mark token with a call to AEDisposeToken, just as for any other final token.
  6772. If your application supports marking, it should also provide a token disposal function modeled after the MyDisposeToken function described on page 2-260. When the Apple Event Manager calls AEDisposeToken to dispose of a mark token that is not the final result of a call to AEResolve, the subsequent call to your token disposal function lets you know that you can unmark the Apple event objects marked with that mark token. A call to AEDisposeDesc to dispose of a mark token (which would occur if you did not provide a token disposal function) would go unnoticed. 
  6773. RESULT CODES
  6774. noErr    0    No error occurred.
  6775. errAEEventNotHandled    –1708    The MyGetMarkToken function is unable to 
  6776.         return a mark token; if the Apple Event 
  6777.         Manager gets this result, it attempts to get a 
  6778.         mark token by calling the equivalent system 
  6779.         marking callback function.
  6780. SEE ALSO
  6781. For more information, see “Writing Marking Callback Functions,” which begins on page 2-179. 
  6782. 2MyMark
  6783. If your application supports marking, you must provide one object-marking function. An object-marking function marks a specific Apple event object. 
  6784. FUNCTION MyMark (theToken: AEDesc; markToken: AEDesc; 
  6785.                         markCount: LongInt): OSErr;
  6786. theToken    The token for the Apple event object to be marked.
  6787. markToken    The mark token used to mark the Apple event object.
  6788. markCount    The number of times MyMark has been called for the current mark token (that is, the number of Apple event objects that have so far passed the test, including the element to be marked).
  6789. DESCRIPTION
  6790. The Apple Event Manager calls the MyMark function provided by your application in order to mark an Apple event object using the current mark token. In addition to marking the specified Apple event object, your MyMark function should record the mark count for each object that it marks. The mark count recorded for each marked Apple event object allows your application to distinguish one set of marked objects from another when a single object specifier record specifies more than one test, as described in the next section for the MyAdjustMarks function.
  6791. RESULT CODES
  6792. noErr    0    No error occurred.
  6793. errAEEventNotHandled    –1708    The MyMark function is unable to mark the 
  6794.         specified Apple event object; if the Apple 
  6795.         Event Manager gets this result, it attempts to 
  6796.         mark the object by calling the equivalent 
  6797.         system object-marking function.
  6798. SEE ALSO
  6799. For more information, see “Writing Marking Callback Functions,” which begins on page 2-179.
  6800. 2MyAdjustMarks
  6801. If your application supports marking, you must provide one mark-adjusting function. A mark-adjusting function adjusts the marks made with the current mark token. 
  6802. FUNCTION MyAdjustMarks (newStart, newStop: LongInt; 
  6803.                                 markToken: AEDesc): OSErr;
  6804. newStart    The mark count value (provided when the MyMark callback routine was called to mark the object) for the first object in the new set of marked objects.
  6805. newStop    The mark count value (provided when the MyMark callback routine was called to mark the object) for the last object in the new set of marked objects.
  6806. markToken    The mark token for the marked objects.
  6807. DESCRIPTION
  6808. When the Apple Event Manager needs to identify either a range of elements or the absolute position of an element in a group of Apple event objects that pass a test, it can use your applications’ mark-adjusting function to unmark objects that it has previously marked with your marking function. For example, if an object specifier record specifies “any row in the table ‘My Customers’ for which the City column is ‘San Francisco’,” the Apple Event Manager first uses the appropriate object accessor function to locate all the rows in the table for which the City column is “San Francisco,” and calls the application’s marking function repeatedly to mark them; it then generates a random number between 1 and the number of rows it found that passed the test, and calls the application’s mark-adjusting function to unmark all the rows whose mark count does not match the randomly generated number. If the randomly chosen row has a mark count value of 5, the Apple Event Manager passes “5” to the mark-adjusting function in both the newStart parameter and the newStop parameter, and passes the current mark token in the markToken parameter. 
  6809. When your application calls your AdjustMyMarks function, your application must dispose of any data structures that it may have created in order to mark the previously marked objects.
  6810. RESULT CODES
  6811. noErr    0    No error occurred.
  6812. errAEEventNotHandled    –1708    The MyAdjustMarks function is unable to 
  6813.         adjust the marks as requested; if the Apple 
  6814.         Event Manager gets this result, it attempts to 
  6815.         adjust the marks by calling the equivalent 
  6816.         system mark-adjusting function. 
  6817. Summary of the Apple Event Manager
  6818. Constants
  6819. CONST        gestaltAppleEventsAttr                                    = 'evnt';                {selector for Apple events}
  6820.         gestaltAppleEventsPresent                                    = 0;                {if this bit is set, then }
  6821.                                                             { Apple Event Manager is }
  6822.                                                             { available}
  6823.  
  6824.         {Apple event descriptor types}
  6825.         typeBoolean                                = 'bool';                    {1-byte Boolean value}
  6826.         typeChar                                = 'TEXT';                    {unterminated string}
  6827.         typeSMInt                                = 'shor';                    {16-bit integer}
  6828.         typeInteger                                = 'long';                    {32-bit integer}
  6829.         typeSMFloat                                = 'sing';                    {SANE single}
  6830.         typeFloat                                = 'doub';                    {SANE double}
  6831.         typeLongInteger                                = 'long';                    {32-bit integer}
  6832.         typeShortInteger                                = 'shor';                    {16-bit integer}
  6833.         typeLongFloat                                = 'doub';                    {SANE double}
  6834.         typeShortFloat                                = 'sing';                    {SANE single}
  6835.         typeExtended                                = 'exte';                    {SANE extended}
  6836.         typeComp                                = 'comp';                    {SANE comp}
  6837.         typeMagnitude                                = 'magn';                    {unsigned 32-bit integer}
  6838.         typeAEList                                = 'list';                    {list of descriptor records}
  6839.         typeAERecord                                = 'reco';                    {list of keyword-specified }
  6840.                                                             { descriptor records}
  6841.         typeAppleEvent                                = 'aevt';                    {Apple event record}
  6842.         typeTrue                                = 'true';                    {TRUE Boolean value}
  6843.         typeFalse                                = 'fals';                    {FALSE Boolean value}
  6844.         typeAlias                                = 'alis';                    {alias record}
  6845.         typeEnumerated                                = 'enum';                    {enumerated data}
  6846.         typeType                                = 'type';                    {Four-character code for }
  6847.                                                             { event class or event ID}
  6848.         typeAppParameters                                = 'appa';                    {Process Manager launch }
  6849.                                                             { parameters}
  6850.         typeProperty                                = 'prop';                    {Apple event property}
  6851.         typeFSS                                = 'fss ';                    {file system specification}
  6852.         typeKeyword                                = 'keyw';                    {Apple event keyword}
  6853.  
  6854.         typeSectionH                                = 'sect';                    {handle to a section record}
  6855.         typeWildCard                                = '****';                    {matches any type}
  6856.         typeApplSignature                                = 'sign';                    {application signature}
  6857.         typeSessionID                                = 'ssid';                    {session ID}
  6858.         typeTargetID                                = 'targ';                    {target ID record}
  6859.         typeProcessSerialNumber
  6860.                                         = 'psn ';                    {process serial number}
  6861.         typeNull                                = 'null';                    {NULL or nonexistent data}
  6862.         
  6863.         {keywords for Apple event parameters}
  6864.         keyDirectObject                                = '----';                    {direct parameter}
  6865.         keyErrorNumber                                = 'errn';                    {error number parameter}
  6866.         keyErrorString                                = 'errs';                    {error string parameter}
  6867.         keyProcessSerialNumber                                = 'psn ';                    {process serial number param}
  6868.  
  6869.         {keywords for Apple event attributes}
  6870.         keyTransactionIDAttr                                = 'tran';                    {transaction ID}
  6871.         keyReturnIDAttr                                = 'rtid';                    {return ID}
  6872.         keyEventClassAttr                                 = 'evcl';                    {event class}
  6873.         keyEventIDAttr                                = 'evid';                    {event ID}
  6874.         keyAddressAttr                                = 'addr';                    {target application}
  6875.         keyOptionalKeywordAttr                                = 'optk';                    {list of optional parameters}
  6876.                                                             { for the Apple event}
  6877.         keyTimeoutAttr                                = 'timo';                    {number of ticks the client }
  6878.                                                             { will wait}
  6879.         keyInteractLevelAttr                                 = 'inte';                    {settings to allow Apple }
  6880.                                                             { Event Mgr to bring }                    
  6881.                                                             { server to foreground}
  6882.         keyEventSourceAttr                                = 'esrc';                    {source application}
  6883.         keyMissedKeywordAttr                                = 'miss';                    {first required parameter }
  6884.                                                             { remaining in an Apple }
  6885.                                                             { event}
  6886.         
  6887.         {keywords for special handlers}
  6888.         keyPreDispatch                                = 'phac';                    {identifies a handler }
  6889.                                                             { routine that is called }
  6890.                                                             { immediately before the }
  6891.                                                             { Apple Event Manager }
  6892.                                                             { dispatches an Apple event}
  6893.         keySelectProc                                = 'selh';                     {another selector}
  6894.  
  6895.  
  6896.  
  6897.         {event class}
  6898.         kCoreEventClass                                = 'aevt';                    {event class for required }
  6899.                                                             { Apple events}
  6900.         {event IDs}
  6901.         kAEOpenApplication                                = 'oapp';                    {event ID for Open }
  6902.                                                             { Application event}
  6903.         kAEOpenDocuments                                = 'odoc';                    {event ID for Open }
  6904.                                                             { Documents event}
  6905.         kAEPrintDocuments                                = 'pdoc';                    {event ID for Print }
  6906.                                                             { Documents event}
  6907.         kAEQuitApplication                                = 'quit';                    {event ID for Quit }
  6908.                                                             { Application event}
  6909.         kAEAnswer                                = 'ansr';                    {event ID for Apple event }
  6910.                                                             { replies}
  6911.         kAEApplicationDied                                = 'obit';                    {event ID for Application }
  6912.                                                             { Died event}
  6913.         
  6914.         {constants for setting the sendMode parameter of AESend and for }
  6915.         { the keyInteractLevelAttr attribute}
  6916.         kAENoReply                                = $00000001;                    {client doesn't want reply}
  6917.         kAEQueueReply                                = $00000002;                    {client wants server to }
  6918.                                                             { reply in event queue}
  6919.         kAEWaitReply                                = $00000003;                    {client wants a reply and }
  6920.                                                             { will give up processor}
  6921.         kAENeverInteract                                = $00000010;                    {server application should }
  6922.                                                             { not interact with user }
  6923.                                                             { for this Apple event}
  6924.         kAECanInteract                                = $00000020;                    {server may interact with }
  6925.                                                             { user for this Apple event }
  6926.                                                             { to supply information}
  6927.         kAEAlwaysInteract                                = $00000030;                    {server may interact with }
  6928.                                                             { user for this Apple event }
  6929.                                                             { even if no information }
  6930.                                                             { is required}
  6931.         kAECanSwitchLayer                                = $00000040;                    {server should come }
  6932.                                                             { directly to foreground }
  6933.                                                             { when appropriate}
  6934.         kAEDontReconnect                                = $00000080;                    {don't reconnect if there }
  6935.                                                             { is a PPC sessClosedErr}
  6936.         kAEWantReceipt                                = nReturnReceipt;
  6937.                                                             {client wants return receipt}
  6938.         
  6939.  
  6940.         {constants for the sendPriority parameter of AESend}
  6941.         kAENormalPriority                                = $00000000;                    {put event at the back of }
  6942.                                                             { event queue}
  6943.         kAEHighPriority                                = nAttnMsg;                    {put event at the front of }
  6944.                                                             { the event queue}
  6945.  
  6946.         {constant for the returnID parameter of AECreateAppleEvent}
  6947.         kAutoGenerateReturnID                                = -1;                    {tells Apple Event Manager }
  6948.                                                             { to generate a unique }
  6949.                                                             { return ID}
  6950.  
  6951.         {constant for transaction IDs}
  6952.         kAnyTransactionID                                 = 0;                    {the Apple event is not }
  6953.                                                             { part of a transaction}
  6954.  
  6955.         {constants for timeout durations}
  6956.         kAEDefaultTimeout                                = -1;                    {use default timeout value}
  6957.         kNoTimeOut                                = -2;                    {never time out}
  6958.  
  6959.         {constants for the dispatcher parameter of AEResumeTheCurrentEvent}
  6960.         kAENoDispatch                                = 0;                    {don't redispatch the }
  6961.                                                             { Apple event}
  6962.         kAEUseStandardDispatch                                = -1;                    {redispatch the Apple event }
  6963.                                                             { by using its entry in the }
  6964.                                                             { Apple event dispatch table}
  6965.  
  6966.         {constants that follow support Apple event objects}
  6967.  
  6968.         {descriptor types used to specify Apple event objects}
  6969.         typeObjectSpecifier                                 =     'obj '                {object specifier record, }
  6970.                                                             { used as keyAEContainer}
  6971.         typeObjectBeingExamined =                                       exmn'                {used as keyAEContainer}
  6972.         typeCurrentContainer                                =    'ccnt'                {used as keyAEContainer}
  6973.         typeToken                                =    'toke'                {substituted for 'ccnt' }
  6974.                                                             { before accessor called}
  6975.         typeRelativeDescriptor                                 =    'rel '                {formRelativePosition}
  6976.         typeAbsoluteOrdinal                                 =    'abso'                {formAbsolutePosition}
  6977.         typeIndexDescriptor                                =    'inde'                {formAbsolutePosition}
  6978.         typeRangeDescriptor                                 =     'rang'                {formRange}
  6979.         typeLogicalDescriptor                                =     'logi'                {formTest}
  6980.         typeCompDescriptor                                =    'cmpd'                {formTest}
  6981.  
  6982.  
  6983.         {descriptor types for whose descriptor records}
  6984.         typeWhoseDescriptor                                =    'whos';
  6985.         typeWhoseRange                                =    'wrng';
  6986.  
  6987.         {logical operators for descriptor records with keyword } 
  6988.         { keyAELogicalOperator}
  6989.         kAEAND                                =    'AND ';                
  6990.         kAEOR                                =    'OR  ';
  6991.         kAENOT                                =    'NOT ';
  6992.  
  6993.         {Absolute ordinals used as key data in an object specifier } 
  6994.         { record with key form formAbsolutePosition}
  6995.         kAEFirst                                =    'firs';
  6996.         kAELast                                =    'last';
  6997.         kAEMiddle                                =    'midd';
  6998.         kAEAny                                =    'any ';
  6999.         kAEAll                                =    'all ';
  7000.  
  7001.         {Relative ordinals used as key data in an object specifier record }
  7002.         { with key form formRelativePosition}
  7003.         kAENext                                =    'next';
  7004.         kAEPrevious                                =    'prev';
  7005.         
  7006.         {keywords for object specifier records} 
  7007.         keyAEDesiredClass                                =    'want';
  7008.         keyAEContainer                                =    'from';
  7009.         keyAEKeyForm                                =    'form';
  7010.         keyAEKeyData                                 =     'seld';
  7011.  
  7012.         {keywords for range data descriptor records}
  7013.         keyAERangeStart                                =    'star';                {beginning of range}
  7014.         keyAERangeStop                                =    'stop';                {end of range}
  7015.     
  7016.         {values for the keyAEKeyForm field of an object specifier record}{                         
  7017.         formAbsolutePosition                                 =    'indx'             ;    {e.g., 1 = first, }
  7018.                                                             { -2 = secondnd from end)}
  7019.         formRelativePosition                                =    'rele' ;                {next, previous}
  7020.         formTest                                =    'test' ;                {A logical or a comparison}
  7021.         formRange                                =    'rang' ;                {Two objects and everything }
  7022.                                                             { in between }
  7023.         formPropertyID                                =    'prop' ;                {key data is a 4-char }
  7024.                                                             { property name}
  7025.         formName                                =    'name' ;                {key data is of type 'TEXT'}
  7026.         formWhose                                =    'whos';                (key data is of descriptor 
  7027.                                                             { type typeWhoseDescriptor}
  7028.  
  7029.         
  7030.         {Additive values for callbackFlags parameter to AEResolve}
  7031.         kAEIDoMinimum                                =    $0000;            {server does not support whose }
  7032.                                                         { descriptor records or marking}
  7033.         kAEIDoWhose                                =    $0001;            {server supports whose }
  7034.                                                         { descriptor records}
  7035.         kAEIDoMarking                                =    $0004;            {server supports marking}
  7036.  
  7037.         {various relevant keywords}
  7038.         keyAECompOperator                                =    'relo';                {operator for comparison: }
  7039.                                                             { '=', '<=', etc.}
  7040.         keyAELogicalTerms                                =    'term';                {an AEList of terms to be }
  7041.                                                             { related by 'logc' below}
  7042.         keyAELogicalOperator                                =    'logc';                    {kAEAND, kAEOR, or kAENOT}
  7043.         keyAEObject1                                =    'obj1';                {first of two objects being }
  7044.                                                             { compared; must be object }
  7045.                                                             { specifier record}
  7046.         keyAEObject2                                =    'obj2';                {the other object; may be }
  7047.                                                             { simple descriptor record }
  7048.                                                             { or object specifier record}
  7049.  
  7050.     {special handler selectors used with AESetObjectCallbacks}
  7051.     keyDisposeTokenProc                                =    'xtok';
  7052.     keyAECompareProc                                 =     'cmpr';
  7053.     keyAECountProc                                 =     'cont';
  7054.     keyAEMarkTokenProc                                 =     'mkid';
  7055.     keyAEMarkProc                                 =     'mark';
  7056.     keyAEAdjustMarksProc                                 =     'adjm';
  7057.     keyAEGetErrDescProc                                 =     'indc';
  7058.  
  7059. {constants for whose descriptor records}
  7060.     typeWhoseDescriptor                                =    'whos';
  7061.     formWhose                                =    'whos';
  7062.     typeWhoseRange                                =    'wrng';
  7063.     keyAEWhoseRangeStart                                =    'wstr';
  7064.     keyAEWhoseRangeStop                                =    'wstp';
  7065.     keyAEIndex                                =    'kidx';
  7066.     keyAETest                                =    'ktst';
  7067.  
  7068. Data Types
  7069. TYPE
  7070.     AEEventClass = 
  7071.         PACKED ARRAY[1..4] OF Char;                                                    {event class for a }
  7072.                                                             { high-level event}
  7073.     AEEventID = 
  7074.         PACKED ARRAY[1..4] OF Char;                                                    {event ID for a high-level }
  7075.                                                             { event}
  7076.     AEKeyword = 
  7077.         PACKED ARRAY[1..4] OF Char;                                                    {keyword for a descriptor }
  7078.                                                             { record}
  7079.  
  7080.     DescType                                    = ResType;                    {descriptor type}
  7081.  
  7082.     AEDesc =                                                         {descriptor record}
  7083.     RECORD        
  7084.         descriptorType:                                 DescType;                    {type of data being passed}
  7085.         dataHandle:                                 Handle;                    {handle to data being passed}
  7086.     END;
  7087.  
  7088.     AEKeyDesc =                                                         {keyword-specified }
  7089.                                                             { descriptor record}
  7090.     RECORD
  7091.         descKey:                                AEKeyword;                    {keyword}
  7092.         descContent:                                AEDesc    ;                {descriptor record}
  7093.     END;
  7094.  
  7095.     AEAddressDesc                                    = AEDesc;                    {address descriptor record}
  7096.  
  7097.     AEDescList                                    = AEDesc;                    {list of descriptor records}
  7098.  
  7099.     AERecord                                    = AEDescList;                    {list of keyword-specified }
  7100.                                                             { descriptor records}
  7101.  
  7102.     AppleEvent                                    = AERecord;                    {list of attributes and }
  7103.                                                             { parameters necessary for }
  7104.                                                             { an Apple event}
  7105.     AESendMode                                    = LongInt;                    {flags that determine how }
  7106.                                                             { an Apple event is sent}
  7107.  
  7108.     AESendPriority                                    = Integer;                    {send priority of an Apple }
  7109.                                                             { event}
  7110.  
  7111.     AEInteractAllowed = (kAEInteractWithSelf, kAEInteractWithLocal,
  7112.                                                    kAEInteractWithAll);
  7113.                                                             {what processes may }
  7114.                                                             { interact with the user}
  7115.  
  7116.     AEEventSource = (kAEUnknownSource, kAEDirectCall, kAESameProcess,
  7117.                                            kAELocalProcess, kAERemoteProcess);
  7118.                                                             {the source of an Apple }
  7119.                                                             { event}
  7120.  
  7121.     AEArrayType = (kAEDataArray, kAEPackedArray, kAEHandleArray, 
  7122.                                     kAEDescArray, kAEKeyDescArray);
  7123.                                                             {type of an Apple event }
  7124.                                                             { array}
  7125.  
  7126.     AEArrayData = 
  7127.     RECORD                                                        {data for an Apple event }
  7128.                                                             { array}
  7129.         case AEArrayType OF
  7130.         kAEDataArray:
  7131.             (AEDataArray:     ARRAY[0..0] OF Integer);
  7132.         kAEPackedArray:    
  7133.             (AEPackedArray:     Packed Array[0..0] OF Char);
  7134.         kAEHandleArray:    
  7135.             (AEHandleArray:     Array[0..0] OF Handle);
  7136.         kAEDescArray:    
  7137.             (AEDescArray:     Array[0..0] OF AEDesc);
  7138.         kAEKeyDescArray:    
  7139.             (AEKeyDescArray:     Array[0..0] OF AEKeyDesc);
  7140.     END;
  7141.     
  7142.     AEArrayDataPointer = ^AEArrayData;
  7143.  
  7144.     EventHandlerProcPtr = ProcPtr;                                                        {pointer to an Apple event }
  7145.                                                             { handler routine}
  7146.  
  7147.  
  7148.     IdleProcPtr = ProcPtr;                                                        {pointer to an app's }
  7149.                                                             { idle function}
  7150.  
  7151.     EventFilterProcPtr = ProcPtr;                                                        {pointer to an app's filter }
  7152.                                                             { procedure}
  7153.  
  7154.     ccntTokenRecord = RECORD                                                        {used for rewriting tokens 
  7155.         tokenClass:                     DescType ;                                { in place of 'ccnt' }
  7156.         token:                     AEDesc ;                                { descriptor records; only }
  7157.         END ;                                                    { of interest to those who, }
  7158.                                                             { when they get ranges as }
  7159.                                                             { key data in their object }
  7160.                                                             { accessor functions, } 
  7161.                                                             { resolve them manually}
  7162.     ccntTokenRecPtr = ^ccntTokenRecord ;
  7163.     ccntTokenRecHandle = ^ccntTokenRecPtr ;
  7164.  
  7165.     DescPtr = ^AEDesc ;
  7166.     DescHandle = ^DescPtr ;
  7167.  
  7168.     AccessorProcPtr = ProcPtr;
  7169. Routines
  7170. Creating and Managing the Apple Event Dispatch Tables
  7171. FUNCTION AEInstallEventHandler
  7172. (theAEEventClass: AEEventClass; theAEEventID: AEEventID; handler: EventHandlerProcPtr; 
  7173. handlerRefcon: LongInt; 
  7174. isSysHandler: Boolean): OSErr;
  7175. FUNCTION AEGetEventHandler    (theAEEventClass: AEEventClass; theAEEventID: AEEventID; VAR handler: EventHandlerProcPtr; 
  7176. VAR handlerRefcon: LongInt; 
  7177. isSysHandler: Boolean): OSErr;
  7178. FUNCTION AERemoveEventHandler
  7179. (theAEEventClass: AEEventClass; theAEEventID: AEEventID; handler: EventHandlerProcPtr; isSysHandler: Boolean): OSErr;
  7180. Initializing the Object Support Library
  7181. FUNCTION AEObjectInit : OSErr;
  7182. Installing Object Accessor Functions and Object Callback Functions
  7183. FUNCTION AESetObjectCallbacks (myCompareProc, myCountProc, 
  7184.                                                                                 myDisposeTokenProc, 
  7185.                                             myGetMarkTokenProc, myMarkProc, 
  7186.                                             myAdjustMarksProc, myGetErrDescProc: 
  7187.                                             ProcPtr): OSErr;
  7188. FUNCTION AEInstallObjectAccessor (desiredClass: DescType; 
  7189.                                             containerType: DescType; 
  7190.                                             theAccessor: AccessorProcPtr; 
  7191.                                             accessorRefcon: LongInt; 
  7192.                                             isSysHandler: Boolean): OSErr;
  7193. Getting, Calling, and Removing Object Accessor Functions
  7194. FUNCTION AEGetObjectAccessor (desiredClass: DescType; 
  7195.                                         containerType: DescType;
  7196.                                         VAR theAccessor: AccessorProcPtr;
  7197.                                         VAR accessorRefcon: LongInt; 
  7198.                                         isSysHandler: Boolean): OSErr;
  7199. FUNCTION AECallObjectAccessor (desiredClass: DescType; 
  7200.                                             containerToken: AEDesc; 
  7201.                                             containerClass: DescType; 
  7202.                                             keyForm: DescType; 
  7203.                                             keyData: AEDesc; 
  7204.                                             VAR theToken: AEDesc): OSErr;
  7205. FUNCTION AERemoveObjectAccessor (desiredClass: DescType; 
  7206.                                             containerType: DescType; 
  7207.                                             theAccessor: AccessorProcPtr; 
  7208.                                             isSysHandler: Boolean): OSErr;
  7209. Dispatching Apple Events
  7210. FUNCTION AEProcessAppleEvent    (theEventRecord: EventRecord): OSErr;
  7211. Getting Data from Apple Event Parameters and Attributes
  7212. FUNCTION AEGetParamPtr    (theAppleEvent: AppleEvent; 
  7213. theAEKeyword: AEKeyword; 
  7214. desiredType: DescType; 
  7215. VAR typeCode: DescType; 
  7216. dataPtr: Ptr; maximumSize: Size; 
  7217. VAR actualSize: Size): OSErr;
  7218. FUNCTION AEGetParamDesc    (theAppleEvent: AppleEvent; 
  7219. theAEKeyword: AEKeyword; desiredType: DescType; 
  7220. VAR result: AEDesc): OSErr;
  7221. FUNCTION AEGetAttributePtr    (theAppleEvent: AppleEvent; 
  7222. theAEKeyword: AEKeyword; desiredType: DescType; 
  7223. VAR typeCode: DescType; 
  7224. dataPtr: Ptr; maximumSize: Size; 
  7225. VAR actualSize: Size): OSErr;
  7226. FUNCTION AEGetAttributeDesc    (theAppleEvent: AppleEvent; 
  7227. theAEKeyword: AEKeyword; desiredType: DescType; 
  7228. VAR result: AEDesc): OSErr;
  7229. Counting the Items in Descriptor Lists
  7230. FUNCTION AECountItems    (theAEDescList: AEDescList; 
  7231. VAR theCount: LongInt): OSErr;
  7232. Getting Items From Descriptor Lists
  7233. FUNCTION AEGetNthPtr    (theAEDescList: AEDescList; index: LongInt; desiredType: DescType; 
  7234. VAR theAEKeyword: AEKeyword; 
  7235. VAR typeCode: DescType; dataPtr: Ptr; maximumSize: Size; 
  7236. VAR actualSize: Size): OSErr;
  7237. FUNCTION AEGetNthDesc    (theAEDescList: AEDescList; index: LongInt; 
  7238. desiredType: DescType; 
  7239. VAR theAEKeyword: AEKeyword; 
  7240. VAR result: AEDesc): OSErr;
  7241. FUNCTION AEGetArray    (theAEDescList: AEDescList; 
  7242. arrayType: AEArrayType; 
  7243. arrayPtr: AEArrayDataPointer; maximumSize: Size; VAR itemType: DescType; VAR itemSize: Size; 
  7244. VAR itemCount: LongInt): OSErr;
  7245. Getting Data and Keyword-Specified Descriptor Records From AE Records
  7246. FUNCTION AEGetKeyPtr    (theAERecord: AERecord; 
  7247. theAEKeyword: AEKeyword; 
  7248. desiredType: DescType; VAR typeCode: DescType; dataPtr: Ptr; maximumSize: Size; 
  7249. VAR actualSize: Size): OSErr;
  7250. FUNCTION AEGetKeyDesc    (theAERecord: AERecord; 
  7251. theAEKeyword: AEKeyword; 
  7252. desiredType: DescType; 
  7253. VAR result: AEDesc): OSErr;
  7254. Resolving Object Specifier Records
  7255. FUNCTION AEResolve     (objectSpecifier: AEDesc; 
  7256.                             callbackFlags: Integer; 
  7257.                             VAR theToken: AEDesc): OSErr;
  7258. Requesting User Interaction
  7259. FUNCTION AESetInteractionAllowed    
  7260. (level: AEInteractAllowed): OSErr;
  7261. FUNCTION AEGetInteractionAllowed    
  7262. (VAR level: AEInteractAllowed): OSErr;
  7263. FUNCTION AEInteractWithUser    (timeOutInTicks: LongInt; nmReqPtr: NMRecPtr; idleProc: IdleProcPtr): OSErr;
  7264. Requesting More Time to Respond to Apple Events
  7265. FUNCTION AEResetTimer    (reply: AppleEvent): OSErr;
  7266. Suspending and Resuming Apple Event Handling
  7267. FUNCTION AESuspendTheCurrentEvent    
  7268. (theAppleEvent: AppleEvent): OSErr;
  7269. FUNCTION AEResumeTheCurrentEvent    
  7270. (theAppleEvent,reply: AppleEvent;             
  7271. dispatcher: EventHandlerProcPtr; handlerRefcon: LongInt): OSErr;
  7272. FUNCTION AESetTheCurrentEvent    (theAppleEvent: AppleEvent): OSErr;
  7273. FUNCTION AEGetTheCurrentEvent    (VAR theAppleEvent: AppleEvent): OSErr;
  7274. Creating Apple Events
  7275. FUNCTION AECreateAppleEvent    (theAEEventClass: AEEventClass; 
  7276. theAEEventID: AEEventID; 
  7277. target: AEAddressDesc; returnID: Integer; transactionID: LongInt; 
  7278. VAR result: AppleEvent): OSErr;
  7279. Creating and Duplicating Descriptor Records
  7280. FUNCTION AECreateDesc    (typeCode: DescType; dataPtr: Ptr; 
  7281. dataSize: Size; VAR result: AEDesc): OSErr;
  7282. FUNCTION AEDuplicateDesc    (theAEDesc: AEDesc; VAR result: AEDesc): OSErr;
  7283. Creating Descriptor Lists and AE Records
  7284. FUNCTION AECreateList    (factoringPtr: Ptr; factoredSize: Size; isRecord: Boolean; 
  7285. VAR resultList: AEDescList): OSErr;
  7286. Creating Object Specifier Records
  7287. FUNCTION CreateOffsetDescriptor (theOffset: LongInt; 
  7288.                                             VAR theDescriptor: AEDesc): 
  7289.                                             OSErr;
  7290. FUNCTION CreateCompDescriptor (comparisonOperator: DescType;
  7291.                                             VAR operand1: AEDesc; 
  7292.                                             VAR operand2: AEDesc; 
  7293.                                             disposeInputs: Boolean; 
  7294.                                             VAR theDescriptor: AEDesc): 
  7295.                                             OSErr;
  7296. FUNCTION CreateLogicalDescriptor (VAR logicalTerms: AEDescList; 
  7297.                                                 logicalOperator: DescType; 
  7298.                                                 disposeInputs: Boolean; 
  7299.                                                 VAR theDescriptor: AEDesc): 
  7300.                                                 OSErr;
  7301. FUNCTION CreateRangeDescriptor (VAR rangeStart: AEDesc; 
  7302.                                             VAR rangeStop: AEDesc; 
  7303.                                             disposeInputs: Boolean; 
  7304.                                             VAR theDescriptor: AEDesc): 
  7305.                                             OSErr;
  7306. FUNCTION CreateObjSpecifier (desiredClass: DescType; 
  7307.                                         VAR theContainer: AEDesc; 
  7308.                                         keyForm: DescType; 
  7309.                                         VAR keyData: AEDesc; 
  7310.                                         disposeInputs: Boolean; 
  7311.                                         VAR objSpecifier: AEDesc): OSErr;
  7312. Adding Items to Descriptor Lists
  7313. FUNCTION AEPutPtr    (theAEDescList: AEDescList; index: LongInt; typeCode: DescType; dataPtr: Ptr; 
  7314. dataSize: Size): OSErr;
  7315. FUNCTION AEPutDesc    (theAEDescList: AEDescList; index: LongInt; theAEDesc: AEDesc): OSErr;
  7316. FUNCTION AEPutArray    (theAEDescList: AEDescList; 
  7317. arrayType: AEArrayType; 
  7318. arrayPtr: AEArrayDataPointer; 
  7319. itemType: DescType; itemSize: Size; 
  7320. itemCount: LongInt): OSErr;
  7321. Adding Data and Keyword-Specified Descriptor Records to AE Records
  7322. FUNCTION AEPutKeyPtr    (theAERecord: AERecord; 
  7323. theAEKeyword: AEKeyword; typeCode: DescType; dataPtr: Ptr; dataSize: Size): OSErr;
  7324. FUNCTION AEPutKeyDesc    (theAERecord: AERecord; 
  7325. theAEKeyword: AEKeyword; 
  7326. theAEDesc: AEDesc): OSErr;
  7327. Adding Parameters and Attributes to Apple Events
  7328. FUNCTION AEPutParamPtr    (theAppleEvent: AppleEvent; 
  7329. theAEKeyword: AEKeyword; typeCode: DescType; dataPtr: Ptr; dataSize: Size): OSErr;
  7330. FUNCTION AEPutParamDesc    (theAppleEvent: AppleEvent; 
  7331. theAEKeyword: AEKeyword; 
  7332. theAEDesc: AEDesc): OSErr;
  7333. FUNCTION AEPutAttributePtr    (theAppleEvent: AppleEvent; 
  7334. theAEKeyword: AEKeyword; typeCode: DescType; dataPtr: Ptr; dataSize: Size): OSErr;
  7335. FUNCTION AEPutAttributeDesc    (theAppleEvent: AppleEvent; 
  7336. theAEKeyword: AEKeyword; 
  7337. theAEDesc: AEDesc): OSErr;
  7338. Sending Apple Events
  7339. FUNCTION AESend    (theAppleEvent: AppleEvent; 
  7340. VAR reply: AppleEvent; sendMode: AESendMode; sendPriority: AESendPriority; 
  7341. timeOutInTicks: LongInt; 
  7342. idleProc: IdleProcPtr; 
  7343. filterProc: EventFilterProcPtr): OSErr;
  7344. Getting the Sizes and Descriptor Types of Descriptor Records
  7345. FUNCTION AESizeOfNthItem    (theAEDescList: AEDescList; index: LongInt; 
  7346. VAR typeCode: DescType; 
  7347. VAR dataSize: Size): OSErr;
  7348. FUNCTION AESizeOfKeyDesc    (theAERecord: AERecord; 
  7349. theAEKeyword: AEKeyword; 
  7350. VAR typeCode: DescType; 
  7351. VAR dataSize: Size): OSErr;
  7352. FUNCTION AESizeOfParam    (theAppleEvent: AppleEvent; 
  7353. theAEKeyword: AEKeyword; VAR typeCode: DescType; VAR dataSize: Size): OSErr;
  7354. FUNCTION AESizeOfAttribute    (theAppleEvent: AppleEvent; 
  7355. theAEKeyword: AEKeyword; VAR typeCode: DescType; VAR dataSize: Size): OSErr;
  7356. Deleting Descriptor Records
  7357. FUNCTION AEDeleteItem    (theAEDescList: AEDescList; 
  7358. index: LongInt): OSErr;
  7359. FUNCTION AEDeleteKeyDesc    (theAERecord: AERecord; 
  7360. theAEKeyword: AEKeyword): OSErr;
  7361. FUNCTION AEDeleteParam    (theAppleEvent: AppleEvent; 
  7362. theAEKeyword: AEKeyword): OSErr;
  7363. Deallocating Memory for Descriptor Records
  7364. FUNCTION AEDisposeDesc    (VAR theAEDesc: AEDesc): OSErr;
  7365. Deallocating Memory for Tokens
  7366. FUNCTION AEDisposeToken (VAR theToken: AEDesc): OSErr;
  7367. Coercing Descriptor Types
  7368. FUNCTION AECoercePtr    (typeCode: DescType; dataPtr: Ptr; 
  7369. dataSize: Size; toType: DescType; 
  7370. VAR result: AEDesc): OSErr;
  7371. FUNCTION AECoerceDesc    (theAEDesc: AEDesc; toType: DescType; 
  7372. VAR result: AEDesc): OSErr;
  7373. Creating and Managing the Coercion Handler Dispatch Tables
  7374. FUNCTION AEInstallCoercionHandler    
  7375. (fromType: DescType; toType: DescType; handler: ProcPtr; handlerRefcon: LongInt; fromTypeIsDesc: Boolean; isSysHandler: Boolean): OSErr;
  7376. FUNCTION AEGetCoercionHandler    
  7377. (fromType: DescType; toType: DescType; 
  7378. VAR handler: ProcPtr; 
  7379. VAR handlerRefcon: LongInt; 
  7380. VAR fromTypeIsDesc: Boolean; 
  7381. isSysHandler: Boolean): OSErr;
  7382. FUNCTION AERemoveCoercionHandler    
  7383. (fromType: DescType; toType: DescType; handler: ProcPtr; 
  7384. isSysHandler: Boolean): OSErr;
  7385. Creating and Managing the Special Handler Dispatch Tables
  7386. FUNCTION AEInstallSpecialHandler    
  7387. (functionClass: AEKeyword; handler: ProcPtr; isSysHandler: Boolean): OSErr;
  7388. FUNCTION AEGetSpecialHandler    (functionClass: AEKeyword; 
  7389. VAR handler: ProcPtr; 
  7390. isSysHandler: Boolean): OSErr;
  7391. FUNCTION AERemoveSpecialHandler    
  7392. (functionClass: AEKeyword; handler: ProcPtr; isSysHandler: Boolean): OSErr;
  7393. Application-Defined Routines
  7394. FUNCTION MyEventHandler    (theAppleEvent: AppleEvent; reply: AppleEvent; handlerRefcon: LongInt): OSErr; 
  7395. FUNCTION MyIdleFunction    (VAR theEventRecord: EventRecord;
  7396. VAR sleepTime: LongInt; 
  7397. VAR mouseRgn: RgnHandle): Boolean;
  7398. FUNCTION MyWaitReplyFilter    (VAR theEventRecord: EventRecord; 
  7399. returnID: LongInt; transactionID: LongInt; sender: AEAddressDesc): Boolean;
  7400. FUNCTION MyCoercePtr    (typeCode: DescType; dataPtr: Ptr; 
  7401. dataSize: Size; toType: DescType; handlerRefcon: LongInt; 
  7402. VAR result: AEDesc): OSErr; 
  7403. FUNCTION MyCoerceDesc    (theAEDesc: AEDesc; toType: DescType; handlerRefcon: LongInt; 
  7404. VAR result: AEDesc): OSErr;
  7405. FUNCTION MyObjectAccessor     (desiredClass: DescType; 
  7406.                                     containerToken: AEDesc; 
  7407.                                     containerClass: DescType; 
  7408.                                     keyForm: DescType; keyData: AEDesc; 
  7409.                                     VAR theToken: AEDesc; 
  7410.                                     theRefcon: LongInt): OSErr;
  7411. FUNCTION MyCountObjects     (desiredType: DescType; 
  7412.                                 containerClass: DescType; 
  7413.                                 theContainer: AEDesc; 
  7414.                                 VAR result: LongInt): OSErr;
  7415. FUNCTION MyCompareObjects     (comparisonOperator: DescType; 
  7416.                                 object: AEDesc; 
  7417.                                 objectOrDescToCompare: AEDesc; 
  7418.                                 VAR result: Boolean): OSErr;
  7419. FUNCTION MyDisposeToken     (VAR unneededToken: AEDesc): OSErr;
  7420. FUNCTION MyGetErrorDesc     (VAR errDescPtr: DescPtr): OSErr;
  7421. FUNCTION MyGetMarkToken     (containerToken: AEDesc; 
  7422.                                     containerClass: DescType; 
  7423.                                     VAR result: AEDesc): OSErr;
  7424. FUNCTION MyMark     (theToken: AEDesc; markToken: AEDesc; 
  7425.                         markCount: LongInt): OSErr;
  7426. FUNCTION MyAdjustMarks (newStart, newStop: LongInt; 
  7427.                                 markToken: AEDesc): OSErr;
  7428. Result Codes
  7429. noErr    0    No error
  7430. paramErr    –50    Parameter error (handler pointer is NIL or odd)
  7431. memFullErr    –108    Not enough room in heap zone
  7432. bufferIsSmall    –607    Buffer is too small
  7433. noOutstandingHLE    –608    No outstanding high-level event
  7434. connectionInvalid    –609    Connection is invalid
  7435. errAECoercionFail    –1700    Data could not be coerced to the requested 
  7436.         descriptor type
  7437. errAEDescNotFound    –1701    Descriptor record was not found
  7438. errAECorruptData    –1702    Data in an Apple event could not be read
  7439. errAEWrongDataType    –1703    Wrong descriptor type
  7440. errAENotAEDesc    –1704    Not a valid descriptor record
  7441. errAEBadListItem    –1705    Operation involving a list item failed
  7442. errAENewerVersion    –1706    Need a newer version of the Apple Event Manager
  7443. errAENotAppleEvent    –1707    Event is not an Apple event
  7444. errAEEventNotHandled    –1708    Event wasn’t handled by an Apple event handler
  7445. errAEReplyNotValid    –1709    AEResetTimer was passed an invalid reply
  7446. errAEUnknownSendMode    –1710    Invalid sending mode was passed
  7447. errAEWaitCanceled    –1711    User canceled out of wait loop for reply or receipt
  7448. errAETimeout    –1712    Apple event timed out
  7449. errAENoUserInteraction    –1713    No user interaction allowed
  7450. errAENotASpecialFunction    –1714    Wrong keyword for a special function
  7451. errAEParamMissed    –1715    Handler cannot understand a parameter the client 
  7452.         considers required
  7453. errAEUnknownAddressType    –1716    Unknown Apple event address type
  7454. errAEHandlerNotFound    –1717    No handler found for an Apple event or a coercion
  7455. errAEReplyNotArrived    –1718    Reply has not yet arrived
  7456. errAEIllegalIndex    –1719    Not a valid list index
  7457. errAEImpossibleRange    –1720     A range like 3rd to 2nd, or 1st to all.
  7458. errAEWrongNumberArgs    –1721    Logical operator kAENOT used with other than 1 term 
  7459. errAEAccessorNotFound     –1723     Accessor proc matching desiredClass and 
  7460.         containerType, or wildcards not found
  7461. errAENoSuchLogical    –1725     Something other than AND, OR, or NOT 
  7462. errAEBadTestKey    –1726     Test is neither typeLogicalDescriptor
  7463.         nor typeCompDescriptor }
  7464. errAENotAnObjSpec    –1727     Param to AEResolve not of type 'obj ' 
  7465. errAENoSuchObject    –1728     A run-time resolution error, for example: specifier 
  7466.         asked for the third, but there are only 2.
  7467. errAENegativeCount    –1729     Object-counting function returned negative value
  7468. errAEEmptyListContainer    –1730     Attempt to pass empty list as container to accessor
  7469. Assembly-Language Information
  7470. Trap Macros Requiring Routine Selectors
  7471. _Pack8
  7472. Selector    Routine
  7473. $011E    AESetInteractionAllowed
  7474. $0204    AEDisposeDesc
  7475. $0219    AEResetTimer
  7476. $021A    AEGetTheCurrentEvent
  7477. $021B    AEProcessAppleEvent
  7478. $021D    AEGetInteractionAllowed
  7479. $022B    AESuspendTheCurrentEvent
  7480. $022C    AESetTheCurrentEvent
  7481. $023A    AEDisposeToken
  7482. $0405    AEDuplicateDesc
  7483. $0407    AECountItems
  7484. $040E    AEDeleteItem
  7485. $0413    AEDeleteKeyDesc
  7486. $0413    AEDeleteParam
  7487. $0500    AEInstallSpecialHandler
  7488. $0501    AERemoveSpecialHandler
  7489. $052D    AEGetSpecialHandler
  7490. $0536    AEResolve
  7491. $0603    AECoerceDesc
  7492. $0609    AEPutDesc
  7493. $0610    AEPutKeyDesc
  7494. $0610    AEPutParamDesc
  7495. $061C    AEInteractWithUser
  7496. $0627    AEPutAttributeDesc
  7497. $0706    AECreateList
  7498. $0720    AERemoveEventHandler
  7499. $0723    AERemoveCoercionHandler
  7500. $0738    AERemoveObjectAccessor
  7501. $0812    AEGetKeyDesc
  7502. $0812    AEGetParamDesc
  7503. $0818    AEResumeTheCurrentEvent
  7504. $0825    AECreateDesc
  7505. $0826    AEGetAttributeDesc
  7506. Selector    Routine
  7507. $0828    AESizeOfAttribute
  7508. $0829    AESizeOfKeyDesc
  7509. $0829    AESizeOfParam
  7510. $082A    AESizeOfNthItem
  7511. $091F    AEInstallEventHandler
  7512. $0921    AEGetEventHandler
  7513. $0937    AEInstallObjectAccessor
  7514. $0939    AEGetObjectAccessor
  7515. $0A02    AECoercePtr
  7516. $0A08    AEPutPtr
  7517. $0A16    AEPutAttributePtr
  7518. $0A22    AEInstallCoercionHandler
  7519. $0A0B    AEGetNthDesc
  7520. $0A0F    AEPutKeyPtr
  7521. $0A0F    AEPutParamPtr
  7522. $0B0D    AEPutArray
  7523. $0B14    AECreateAppleEvent
  7524. $0B24    AEGetCoercionHandler
  7525. $0C3B    AECallObjectAccessor
  7526. $0D0C    AEGetArray
  7527. $0D17    AESend
  7528. $0E11    AEGetKeyPtr
  7529. $0E11    AEGetParamPtr
  7530. $0E15    AEGetAttributePtr
  7531. $0E35    AESetObjectCallbacks
  7532. $100A    AEGetNthPtr
  7533.  
  7534.  
  7535. ¶@ˇ ˇˇˇˇ@
  7536. ˇ·ˇ‚7^, Palatino
  7537. .Ä(*
  7538. 4^Hÿ
  7539. ˇˇ≥>ˇ◊°dONLNdƒHÂ.(›HInside Macintosh:
  7540. H    4H     H
  7541. ˇ·ˇ‚7^°dONLNd‰Hï* Collaborative Computing
  7542. à∫ÿ4à∫ÿ4üªË
  7543. °dONLNdˇˇ(ߪPreliminary Draft
  7544. ∂ª‘4∂ª”4πª–l
  7545.     °dONLNdˇˇ* Developer TÎ@°dONLNdˇˇ)0echnical Publications°dONLNdˇˇ(Àª© $P°dONLNdˇˇ)    Apple ComputerZ†°dONLNdˇˇ)C , Inc. 1992
  7546. à∫ÿ
  7547. ÄQ°dONLNdˇˇ(öªˇ™@ˇ ˇˇˇˇ@
  7548. ˇ·ˇ‚7^
  7549. 4⁄`˙º4^*¿∫, Palatino
  7550. .°dONLNd\*h1+*ee‡°dONLNd\2hï)Apple Computer, Inc. °dONLNdz*Ü≠(É*© 1991, Apple Computer, Inc.°dONLNd5Ñ*ê*
  7551. All rights reserved.°dONLNdJì*ü±* Printed in the United States of °dONLNdkù*©R*
  7552. America.°dONLNdt¨*∏±*The Apple logo is a registered °dONLNdì∂*¬∂*
  7553. trademark of Apple Computer, °dONLNd∞¿*â*
  7554. Inc. Use of the “keyboard” °dONLNdà*÷∏*
  7555.  Apple logo (Option-Shift-K) for °dONLNdÏ‘*‡∞*
  7556. commercial purposes without °dONLNdfi*Í•*
  7557. the prior written consent of ˇˇN∑°dONLNd&Ë*Ùπ*
  7558. Apple may constitute trademark °dONLNdEÚ*˛∏*
  7559. infringement and unfair compe-°dONLNdc¸*π*
  7560. #tition in violation of federal and °dONLNdÜ*X*
  7561. state laws.°dONLNdí*!ç*Apple Computer, Inc. °dONLNd®*+í*
  7562. 20525 Mariani Avenue  °dONLNdø)*5†*
  7563. Cupertino, CA  95014-6299°dONLNdŸ3*?g*
  7564. 408-996-1010  °dONLNdËB*N≥*Apple, the Apple logo, APDA, °dONLNdL*Xò*
  7565. AppleLink, AppleShare, °dONLNdV*bÇ*
  7566. AppleTalk, Apple II
  7567. P@°dONLNd0XÉaå)YGS
  7568. ù°dONLNd2Vçb≥)
  7569. , A/UX, °dONLNd:`*l≤(i*EtherTalk, HyperCard, Hyper-°dONLNdVj*vπ*
  7570.  Talk, ImageWriter, LaserWriter, °dONLNdvt*Ä•*
  7571. LocalTalk, Mac, Macintosh, °dONLNdë~*ä∑*
  7572. MPW, MultiFinder, SANE, and °dONLNd≠à*îµ*
  7573. TokenTalk are registered trade-°dONLNdÃí*û≥*
  7574. marks of Apple Computer, Inc.°dONLNdͰ*≠©*Apple Desktop Bus, Balloon °dONLNd´*∑≥*
  7575. Help, Finder, KanjiTalk, Moof, ˇˇÁ˰dONLNd$µ*¡π*
  7576. QuickDraw, ResEdit, TrueType, °dONLNdBø*Àµ*
  7577. and Zhong-Wen Talk are trade-°dONLNd_…*’≥*
  7578. marks of Apple Computer, Inc.°dONLNd}ÿ*‰ó*Helvetica and Times are °dONLNdñ‚*Óô*
  7579. registered trademarks of °dONLNd∞Ï*¯Ç*
  7580. Linotype Company.ˇˇ%~°dONLNd¬˚*π*"ITC Zapf Dingbats is a registered °dONLNd‰*¢*
  7581. trademark of International °dONLNdˇ*ç*
  7582. Typeface Corporation.°dONLNd**∞*MacPaint is a registered trade-°dONLNd4(*4§*
  7583. mark of Claris Corporation.°dONLNdP7*C¥*NuBus is a trademark of Texas °dONLNdoA*Mb*
  7584. Instruments.°dONLNd|P*\≥*!PostScript is a registered trade-°dONLNdùZ*fô*
  7585. mark, and Illustrator is a °dONLNdπd*pØ*
  7586. trademark, of Adobe Systems °dONLNd÷n*zf*
  7587.  
  7588. Incorporated.ˇˇ3√°dONLNd‰}*âπ*"Sony is a registered trademark of °dONLNdá*ì{*
  7589. Sony Corporation.°dONLNdñ*¢∑*UNIX is a registered trademark °dONLNd7†*¨∞*
  7590. of UNIX System Laboratories, °dONLNdT™*∂:*
  7591. Inc.4^…¿YˇˇÜW°dONLNdY\…hX(e… Simultaneously published in the °dONLNdyf…r>*
  7592. United States and Canada.°dONLNdìé…öJ*(Limited Warranty on Media °dONLNd≠ò…§*
  7593. and Replacement°dONLNdΩ©…µ3*Even though Apple has °dONLNd‘≥…ø.*
  7594. reviewed this manual, û‡°dONLNdÍ≥.øP)eAPPLE ˇˇ±°dONLNdΩ……S(Δ…MAKES NO WARRANTY OR ˇ˛ùǰdONLNd«…”S*
  7595. REPRESENTATION, EITHER °dONLNd—…›;*
  7596. EXPRESS OR IMPLIED, °dONLNd0€…ÁE*
  7597. WITH RESPECT TO THIS °dONLNdEÂ…ÒE*
  7598. MANUAL, ITS QUALITY, °dONLNdZÔ…˚I*
  7599. ACCURACY, MERCHANT-°dONLNdm˘…N*
  7600. ABILITY, OR FITNESS FOR °dONLNdÖ…N*
  7601. A PARTICULAR PURPOSE. °dONLNdõ
  7602. …,*
  7603. AS A RESULT, THIS °dONLNdÆ…#<*
  7604. MANUAL IS SOLD “AS °dONLNd¬!…-C*
  7605. IS,” AND YOU, THE PUR-°dONLNdÿ+…7M*
  7606. CHASER, ARE ASSUMING °dONLNdÌ5…AF*
  7607. THE ENTIRE RISK AS TO °dONLNd?…K(*
  7608. ITS QUALITY AND °dONLNdI…U *
  7609. ACCURACY.  °dONLNd Z…fO*IN NO EVENT WILL APPLE °dONLNd7d…pC*
  7610. BE LIABLE FOR DIRECT, °dONLNdNn…z1*
  7611. INDIRECT, SPECIAL, °dONLNdbx…ÑJ*
  7612. INCIDENTAL, OR CONSE-°dONLNdwÇ…é;*
  7613. QUENTIAL DAMAGES °dONLNdâå…òB*
  7614. RESULTING FROM ANY °dONLNdùñ…¢O*
  7615. DEFECT OR INACCURACY °dONLNd≤†…¨'*
  7616. IN THIS MANUAL, {†°dONLNd¬†(¨H)_even if °dONLNd ™…∂E(≥…advised of the possibility of °dONLNdË¥…¿*
  7617. such damages.  °dONLNd¯≈…—;*THE WARRANTY AND °dONLNd    œ…€=*
  7618. REMEDIES SET FORTH °dONLNdŸ…ÂD*
  7619. ABOVE ARE EXCLUSIVE °dONLNd0„…Ô3*
  7620. AND IN LIEU OF ALL °dONLNdDÌ…˘**
  7621. OTHERS, ORAL OR °dONLNdU˜…?*
  7622. WRITTEN, EXPRESS OR °dONLNdj…
  7623. ˙*
  7624.     IMPLIED. Ó`°dONLNds˙
  7625. H)1No Apple dealer, °dONLNdÑ …)(…agent, or employee is °dONLNdõ…!4*
  7626. authorized to make any °dONLNd≥…+A*
  7627. modification, extension, or °dONLNd–)…5?*
  7628. addition to this warranty.  °dONLNdÌ:…FI*Some states do not allow the °dONLNd    
  7629. D…P:*
  7630. exclusion or limitation of °dONLNd    &N…ZO*
  7631.  implied warranties or liability °dONLNd    FX…dR*
  7632.  for incidental or consequential °dONLNd    fb…n/*
  7633. damages, so the above ˇˇpr°dONLNd    }l…xS*
  7634.  limitation or exclusion may not °dONLNd    ùv…ÇG*
  7635. apply to you. This warranty °dONLNd    πÄ…åP*
  7636. !gives you specific legal rights, °dONLNd    ⁄ä…ñK*
  7637. and you may also have other ˇˇ‘Ô°dONLNd    ˆî…†S*
  7638.  rights which vary from state to °dONLNd
  7639. û…™‡*
  7640. state.4^h¿¯ˇÊ@ˇ ˇˇˇˇ@
  7641. ˇ·ˇ‚7^
  7642. 4⁄∫˙,     Helvetica
  7643.     .(‡∫Contents
  7644. 
  7645. ‡(‡1ù)-‡)1
  7646. (Ô∫Draft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/92, Palatino
  7647.         (#∫CHAPTER )~1
  7648. ~H-4~H- H
  7649. °dONLNdˇˇ('∫Contents
  7650. ˇ·ˇ‚7^
  7651. ˇˇf|ˇÆ°dONLNd]∫{≈(t∫The Edition Manager
  7652. °dONLNd<∫H3*—About the Edition Manager¿°dONLNd/<HHU)é1-3°dONLNd3I∫U](R∫%Publishers, Subscribers, and Editions°dONLNdZIrU)∏1-4°dONLNd^V∫b4(_∫Using The Edition Manager,`°dONLNdyVIb[)è1-12°dONLNd~cƒoÚ(lƒ
  7653. Receiving *†°dONLNdàcÚo9).Apple Events Frÿ†°dONLNdóc9o§)Gom the Edition Manager£°dONLNdØcπoÀ)Ä1-12°dONLNd¥pƒ|œ(yƒCr\°dONLNd∂pœ|8) eating the Section Recor‡°dONLNdŒp9|U)jd and Δ`°dONLNd‘pT|Ü) Alias Recor=¿°dONLNdflpá|ç)3dYİdONLNd‚p°|≥)1-15°dONLNdÁ}ƒâu(܃%Saving a Document Containing Sections’İdONLNd}ââõ)≈1-19°dONLNdäƒñµ(ìƒ2Opening and Closing a Document Containing SectionsP`°dONLNdGä ñ‹(ì 1-22°dONLNdLóƒ£(†ƒ
  7654. Reading and Wå°dONLNdYó£J)Driting a Section›Ä°dONLNdkó^£p)V1-25°dONLNdp§Œ∞-(≠ŒFormats in an Editiong@°dONLNdá§B∞T)t1-25°dONLNd屌Ω%(∫ŒOpening an Edition§¿°dONLNd†±9ΩK)k1-27°dONLNd•挠 («Œ Format MarksA†°dONLNd≥æ! 3)S1-27°dONLNd∏ÀŒ◊(‘Œ
  7655. Reading and Wå°dONLNd≈À◊d)Driting Edition DataÉ`°dONLNd⁄Ày◊ã)g1-28°dONLNdflÿŒ‰ (·ŒClosing an Edition›†°dONLNdÛÿ4‰F)f1-28°dONLNd¯ƒÒœ(ÓƒCr\°dONLNd˙œÒ) eating a Publisher‰†°dONLNdÂ2ÒD)c1-29°dONLNdÚŒ˛Ÿ(˚ŒCr\°dONLNdÚŸ˛V) eating the Edition Container∂°dONLNd3Új˛|)ë1-32°dONLNd8ˇŒ k(Œ!Opening an Edition Container to W5İdONLNdYˇk ë)ù    rite Dataú °dONLNddˇ• ∑):1-35°dONLNdi ƒœ(ƒCr\°dONLNdk œ") eating a SubscriberKİdONLNdÄ 7I)h1-37°dONLNdÖŒ%è("Œ)Opening an Edition Container to Read Data‡°dONLNd∞§%∂)÷1-41°dONLNdµ&Œ2Å(/Œ%Choosing Which Edition Format to Read?°dONLNd‹&ñ2®)»1-41°dONLNd·3ƒ?u(<ƒ&Using Publisher and Subscriber Options@°dONLNd    3ä?ú)Δ1-43°dONLNd@ŒL∂(IŒ1Publishing a New Edition While Saving or Manuallyq¿°dONLNdA@ÀL›)˝1-47°dONLNdFMŒY@(VŒSubscribing to an Edition c†°dONLNd`M@Y∏)rAutomatically or ManuallyŒÄ°dONLNd{MÃYfi)å1-48°dONLNdÄZŒf-(cŒCanceling Sections Wo °dONLNdîZ-fv)_ithin Documents=İdONLNd•Zãfù)^1-48°dONLNd™gŒs;(pŒLocating a Publisher Thrw†°dONLNd¬g;sä)mough a SubscriberÔ`°dONLNd’gûs∞)c1-49°dONLNd⁄tƒÄÑ(}ƒ'Renaming a Document Containing Sections İdONLNdtôÄ´)’1-50°dONLNdŃçw(äƒ'Displaying Publisher and Subscriber Bor6‡°dONLNd/Åxçã)¥dersK‡°dONLNd5Åüç±)'1-50°dONLNd:éŒö‘(óŒTµ¿°dONLNd;é”öÚ)ext Bor¿†°dONLNdBéÚö)ders’†°dONLNdHéö+)'1-54°dONLNdMõŒß›(§ŒSpr܇°dONLNdPõ›ß) eadsheet Bor&İdONLNd\õß))9ders;İdONLNdbõ=ßO)'1-55°dONLNdg®Œ¥Q(±ŒObject-Oriented Graphics Bor◊ °dONLNdÉ®Q¥d)ÉdersÏ °dONLNdâ®x¥ä)'1-55°dONLNd鵌¡;(æŒBitmapped Graphics Bor◊@°dONLNd§µ;¡N)mdersÏ@°dONLNd™µb¡t)'1-57ˇ
  7656. @ˇ ˇˇˇˇ@
  7657. ˇ·ˇ‚7^
  7658. 4*\˜, Palatino
  7659. .+ú"CHAPTER €`)\14⁄*˙¯,     Helvetica
  7660. (‡*1 )-c)2
  7661.     )iContents
  7662. *Draft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯
  7663. °dONLNd\∞h^(e∞&Duplicating Publishers and Subscribers»@°dONLNd(\rhÑ)¬1-57°dONLNd-i¶u
  7664. (r¶Modifying a Subscriber5`°dONLNdEi"u4)|1-59°dONLNdJv¶Ç(¶Relocating an Edition≥‡°dONLNdavÇ+)s1-59°dONLNdfɶè(å¶Customizing Dialog BoxesÎ`°dONLNdÄÉ/èA)â1-59°dONLNdÖêúúÿ(ôú
  7665. Subscribing T]°dONLNdíêÿú.)<o Non-Edition Files¥ °dONLNdßêBúT)j1-62°dONLNd¨ù¶©Ô(¶¶Getting the CurrkİdONLNdºùÔ©C)Ient Edition Opener†°dONLNd–ùX©j)i1-63°dONLNd’™¶∂(≥¶Setting an Edition Openero °dONLNd™-∂?)á1-63°dONLNdı∑¶√&(¿¶Calling an Edition Opener Pr`°dONLNd∑'√E)ÅocedurƆ°dONLNd∑E√I)ex@°dONLNd∑^√p)1-63°dONLNdƒ¶–+(Õ¶Opening and Closing Editionsx@°dONLNd=ƒ@–R)ö1-67°dONLNdB—¶›P(⁄¶&Listing Files That Can Be Subscribed TƆ°dONLNdh—O›T)©o$ °dONLNdk—i›{)1-67°dONLNdpfi¶Í÷(Á¶
  7666. Reading Fr0`°dONLNdzfi◊Í)1om and W©†°dONLNdÇfiÍ>)-riting to Files.@°dONLNdìfiSÍe)O1-67°dONLNdòζ˜(Ù¶Calling a Format I/O Pr÷İdONLNdØÎ˜.)jocedurm¿°dONLNdµÎ/˜3)e7`°dONLNd∏ÎH˜Z)1-68°dONLNdΩ¯ú≥(úRefer⁄ °dONLNd¬¯≥/)ence to the Edition Managerg¿°dONLNdfl¯DV)ë1-69°dONLNd‰¶Õ(¶Routines≠`°dONLNdÓ·Û);1-70°dONLNdÛ∞=(∞ Initializing the Edition Manager]İdONLNdRd)¢1-70°dONLNd∞+ª((∞Cr\°dONLNdª+H)  eating and Registering a Section¸‡°dONLNd>\+n)°1-71°dONLNdC,∞8ª(5∞Cr\°dONLNdE,ª8p) (eating and Deleting an Edition Container[@°dONLNdo,Ö8ó) 1-76°dONLNdt9¶EE(B¶"Setting and Locating a Format MarkUİdONLNdò9ZEl)¥1-77°dONLNdùF¶R(O¶Reading in Edition Data' °dONLNd∂F%R7)1-79°dONLNdªS∞_∫(\∞W¬†°dONLNdºSπ_)    riting out Edition Data˘°dONLNd’S1_C)x1-81°dONLNd⁄`∞l(i∞Closing an Edition ˇ@°dONLNdÌ`lZ)TAfter Reading or W °dONLNdˇ`[ls)WritingÜ@°dONLNd`álô),1-83°dONLNd m∞y(v∞Displaying Dialog Boxesx@°dONLNd%m1yC)Å1-85°dONLNd*z∞ÜM(É∞#Locating a Publisher and Edition Frì@°dONLNdMzMÜì)ùom a Subscriberw`°dONLNd^z®Ü∫)[1-92°dONLNdcá∞ì%(ê∞Edition Container Formatsr`°dONLNd~á:ìL)ä1-94°dONLNdÉî∞†Ù(ù∞
  7667. Reading and Wå°dONLNdêîÙ†])Driting Non-Edition Files”‡°dONLNd™îq†É)}1-95°dONLNdذú≠0(™úSummary of the Edition Manager∫‡°dONLNdœ°D≠V)®1-98ˇ @ˇ ˇˇˇˇ@
  7668. ˇ·ˇ‚7^, Palatino
  7669. .+ä"CHAPTER 
  7670. 4⁄ä˙,     Helvetica
  7671.     (‡äAbout the Edition Manager
  7672. 
  7673. ‡(‡1ù)-‡)3
  7674. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/92("È1
  7675.     ˇˇ—ÚˇÆ°dONLNd8äC⁄(@äThe Edition Managerˇˇˇˇˇˇ≠>(@1
  7676. °dONLNd\äh¸(eäRThis chapter describes how you can use the Edition Manager to allow your users to °dONLNdfhätù* sharS`°dONLNdjhùt5)"e and automatically update data fr¿°dONLNdåh5tc)òom numerƒ†°dONLNdîhct˜). ous documents and applications. °dONLNdµzäÜÇ(Éä7The Edition Manager is available only in system softwar˚@°dONLNdÏzÇÜ )¯!e version 7.0. It can be used by °dONLNd
  7677. Üäí≤(èämany dif^‡°dONLNdÜ≤íæ)(ferA`°dONLNdÜæíâ) 0ent applications located on a single disk or thrò`°dONLNdHÜâíÎ)Àoughout a network of °dONLNd]íäû∏(õä    Macintosh
  7678. ÂİdONLNdˇˇ(ó∏®
  7679. flİdONLNdyíæû˙+
  7680.  computers. T쇰dONLNdÜí˙ûƒ)</o test for the existence of the Edition Manageri‡°dONLNdµíƒû ) , use the Gestalt °dONLNd«ûä™’(ßäKfunction, described in the Compatibility Guidelines chapter of this volume.°dONLNd∞äº*URead the information in this chapter if you want your application’s documents to sharO‡°dONLNdh∞º
  7681. (πe °dONLNdjºä»u(≈ä5and automatically update data, or if you want to shar0@°dONLNdüºv»)Ï e and automatically update data °dONLNdø»ä‘‹(—äwith documents crˇ`°dONLNd–»‹‘Í)R<eated by other applications that support the Edition ManagerÕ`°dONLNd »Í‘Ï(—Í.°dONLNd⁄äÊ@(„ä(For example, a user might want to capturÙ¿°dONLNd6⁄@Êe)∂    e sales fi˜ °dONLNd@⁄eÊt)%gurR`°dONLNdC⁄uʵ)es and totals fr˛†°dONLNdS⁄µÊÏ)@ om within a °dONLNd_ÊäÚò(ÔäsprÑ °dONLNdbÊòÚ|)3eadsheet and then include this information in a wor(°dONLNdïÊ}Úê)Âd-pr^¿°dONLNdôÊêÚ˚)ocessing document that °dONLNd∞Úä˛˙(˚äQsummarizes sales for a given month. The Edition Manager establishes a connection °dONLNd˛ä
  7682. l* .between these two documents. When a user modifiÄ@°dONLNd0˛l
  7683. ñ)‚
  7684. es the sprh`°dONLNd:˛ñ
  7685. )*eadsheet, the information in °dONLNdW
  7686. ä¨(äthe worn‡°dONLNd^
  7687. ¨ø)"d-pr•†°dONLNdb
  7688. øÙ)Eocessing document can be automatically updated to contain the latest °dONLNdßä"∏(ä
  7689. changes. T^İdONLNd±∏">).o accomplish this, both the spr
  7690. ¿°dONLNd–?"“)á eadsheet application and the worÁ°dONLNd—"‰)íd-pr¿°dONLNdÙÂ" )    ocessing °dONLNd˝"ä.'(+ä#application must support the featur熰dONLNd "'.ò)ùes of the Edition Manager° °dONLNd9"ò.ö)q.°dONLNd;4ä@ê(=äTµ¿°dONLNd<4è@‹)o use this chapterw °dONLNdN4‹@õ)M+, you should be familiar with sending and r¯¿°dONLNdy4õ@)øeceiving high-level events, °dONLNdï@äLÖ(Iä8described in the Events Manager chapter of this volume.  @°dONLNdÕ@ÜLå)¸Y‡¿°dONLNdŒ@ãL˛)our application must also °dONLNdËLäXØ(Uäsupport îİdONLNdLØX )%Apple
  7691. °dONLNdˇˇ(QÀ®
  7692.  °dONLNdL—X+  events to rì °dONLNdLX)0eceive İdONLNdLXc)Apple events fr1 °dONLNd*LcXŒ)Dom the Edition Manager> °dONLNd@LŒXÙ)k
  7693. . See the ê °dONLNdJLÙX)&Apple °dONLNdPXäd¢(aä>Event Manager chapter in this volume for detailed information.
  7694. iHÑ4jHÑ
  7695. ïHù4ñHù ñHñ
  7696. ˇ·ˇ‚7^
  7697. ˇˇ£‰ˇÆ°dONLNdèÇHî(êHAbout the Edition Managerˇˇˇˇˇˇ⁄|(ê 1
  7698. °dONLNd©•ä±Ù(ÆäThe Edition Manager pr¶`°dONLNdø•Ù±u)jovides you with the ability to,
  7699.  
  7700. Zapf Dingbats
  7701. °dONLNdfi∫ä¡è(¿än
  7702. °dONLNd‡∑ñ√≤) captur‡°dONLNdÊ∑≥√—)?e data within a document and integrate it into another document
  7703. °dONLNd&Ãä”è(“än
  7704. °dONLNd(…ñ’˚) Lmodify information in a document and automatically update any document that °dONLNdt’ñ·©* sharS`°dONLNdx’©·‘) es its data
  7705. °dONLNdÑÍäÒè(än
  7706. °dONLNdÜÁñÛ©) sharS`°dONLNdäÁ©Û≈)>e information between applications on the same computer or acr˘`°dONLNd»Á≈Û(≈oss a network of °dONLNdŸÛñˇı(¸ñMacintosh computers°dONLNdÌäï(ä=Building the capabilities of the Edition Manager into your prİdONLNd*ñ(ñogram is similar to building °dONLNdGä„(äcut-and-paste featur≈¿°dONLNd[„#)Yes into your prÉİdONLNdj$K)Aogram. TÑİdONLNdrKñ)'ext, graphics, spr® °dONLNdÑñ)Keadsheet cells, database °dONLNdùä)ç(&ärE°dONLNdûé))Xeports—any data that you can select, you can make accessible to other applications that °dONLNdˆ)ä5
  7707. (2äsupport the Edition Manager6`°dONLNd    )
  7708. 5 )Ä.°dONLNd    ;äG…(DäThis chapter fiʆ°dONLNd    ";…GÁ)?rst defi ¿°dONLNd    *;ËG
  7709. )@nes the main elements of the Edition Manager and then discusses °dONLNd    jGäS„(Pähow to save, open, rZ@°dONLNd    ~G„SÇ)Y#ead, and write a document that sharŒ@°dONLNd    °GÇS)ü#es data. In addition, this chapter °dONLNd    ƒSä_‘(\ädescribes how to
  7710. °dONLNd    ’häoè*n
  7711. °dONLNd    ◊eñqO) *make data accessible to other applications
  7712. °dONLNd
  7713. zäÅè(Ään
  7714. °dONLNd
  7715. wñÉ) integrate data into numer^`°dONLNd
  7716. wÉJ)q
  7717. ous documents
  7718. °dONLNd
  7719. +åäìè(íän
  7720. °dONLNd
  7721. -âñïÁ) set update options
  7722. °dONLNd
  7723. @ûä•è(§än
  7724. °dONLNd
  7725. Bõñß◊)
  7726. implement bor‰°dONLNd
  7727. Oõ◊ßÍ)Aders
  7728. °dONLNd
  7729. T∞ä∑è(∂än
  7730. °dONLNd
  7731. V≠ñπÀ) modify shar°dONLNd
  7732. a≠ÃπÏ)6ed dataˇ @ˇ ˇˇˇˇ@
  7733. ˇ·ˇ‚7^
  7734. 4*\˜, Palatino
  7735. .+l"CHAPTER €`)\1,     Helvetica
  7736.     (@lThe Edition Manager4⁄*˙¯
  7737. (‡*1 )-c)4
  7738.     )9%Publishers, Subscribers, and Editions
  7739. *Draft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯,
  7740.  
  7741. Zapf Dingbats
  7742. °dONLNd_lfq(eln
  7743. °dONLNd\xhfl) customize dialog boxes°dONLNdnlz:(wl.This chapter also describes an advanced featurW°dONLNdGn:zÀ)Œ"e that allows applications to sharP °dONLNdinÀzË)ëe data °dONLNdpzlÜx(ÉldirI °dONLNdszyÜó)
  7744. ectly fr’¿°dONLNd{zóܵ)om a fi,°dONLNdÇz∂Ü¿)le.
  7745. ã*¶¯4å*¶¯
  7746. ∑*ø¯4∏*ø¯ ∏*∏˛
  7747. ˇ·ˇ‚7^
  7748. ˇˇ£‰ˇÆ°dONLNdܧ*∂F(≤*%Publishers, Subscribers, and Editionsˇˇˇˇˇˇ⁄|(≤Ó1
  7749. °dONLNd¨«l”s(–lA∫†°dONLNd≠«s”u) :†°dONLNdÆ«v”ñ)sectionm¿°dONLNdµ«ñ”5) % is a portion of a document that shar‡°dONLNd⁄«6”Ô)†*es its contents with other documents. The °dONLNd”lflø(‹lLEdition Manager supports two types of sections: publishers and subscribers. x@°dONLNdP”øflΔ(‹øA≤‡°dONLNdQ”Δfl») °dONLNdRfllÎò(Ël    publisher͆°dONLNd[flòλ),G is a section within a document that makes its data available to other °dONLNd¢Îl˜Ê(Ùldocuments or applications. t†°dONLNdΩÎʘÌ)zAØ@°dONLNdæÎ̘Ô) /@°dONLNdøÎ˜)
  7750. subscriberÓ`°dONLNd…ΘÌ)/1 is a section within a document that obtains its °dONLNd˙˜lâ(ldata frw°dONLNd˜â+)#om other documents or applications.°dONLNd%    lr(lY@İdONLNd&    rµ)Kour application writes a copy of the data in each publisher to a separate fi¿°dONLNdr    ∂Í(∂
  7751. le called an °dONLNdl!∫(ledition container˜‡°dONLNdêπ!ª)M.w‡°dONLNdëº!ª)> The actual data that is written to the edition container is r/†°dONLNdœº!–(ºeferrŒ`°dONLNd‘–!Ù)    ed to as °dONLNd›!l-|(*lthe ›`°dONLNd·!|-°)    edition. r°dONLNdÍ!¢-®)&Y2İdONLNdÎ!®-û)9our application obtains the data for each subscriber by rÖ@°dONLNd$!û-€)ˆeading data fr*İdONLNd2!‹-Ï)>om °dONLNd5-l9«(6lthe edition containerN‡°dONLNdJ-«9)[. Note that thrN °dONLNdY-9a)>oughout this chapter®`°dONLNdm-`9å)[ , the term X`°dONLNdx-ç9®)-edition¿°dONLNd-©9Ø) rb¿°dONLNdÅ-Ø9‚)
  7752. efers to the °dONLNdé9lE%(Bl,edition container and the data it contains. °dONLNdªKlWr*Y@İdONLNdºKrW)ou = °dONLNdøKÄW£)publishƒ °dONLNdΔK£W«)#@ data when you want to make it available to other documents and °dONLNdWlc7(`l0applications. When data is published, it is storC °dONLNd6W8c©)Ãed in an edition container• °dONLNdPW®c≠)p. wİdONLNdRW≠c≥)Y8°dONLNdSW≥c¿)ou 4†°dONLNdVW¡cÏ)    subscribe °dONLNd_WÌcÔ), °dONLNd`clo/(ll-to data that a publisher makes available by rİdONLNdçc0oá)ƒeading an edition frÊ`°dONLNd°cÜoÕ)Vom its containerI¿°dONLNd±cÕo“)G. 
  7753. |*â¯4}*à¯
  7754. °dONLNdˇˇ(ÑlNOTE
  7755. ˇ·ˇ‚7^
  7756. °dONLNd¥Ülíâ* Section °dONLNdªÜäíü) and  @°dONLNd¿܆í‰)edition containerD†°dONLNd—܉íÔ)D ar↰dONLNd‘ÜÔí) e prö`°dONLNdÿÜíU)ogrammatic terms. 6†°dONLNdÍÜVí\)VY˜ °dONLNdÎÜ[íõ)ou should not °dONLNd˘ílûl(õl8use them in your application or your documentation. Use  °dONLNd1ímûò(õm publishers,€@°dONLNd<íòûö)+ °dONLNd=ûl™õ(ßl subscribers,°dONLNdIûú™±)0 and Ì °dONLNdNû±™–)editionsñ °dONLNdVû—™÷) . hİdONLNdXû÷™‹)Y)°dONLNdYû‹™#)ou should also r†°dONLNdiû#™F)G    efrain frw`°dONLNdrûF™ã)#om using other °dONLNdÅ™l∂™(≥lterms such as “`°dONLNdè™™∂◊)> publication-†°dONLNdö™ÿ∂Ê). or ï¿°dONLNdû™Ê∂) subscriptiond`°dONLNd™™∂Ü)2 to describe the dynamic °dONLNd√∂l¬‹(ølsharing of information prï¿°dONLNd‹∂‹¬f)povided by the Edition Managerı@°dONLNd˘∂e¬ç)â
  7757. . Use the °dONLNd¬lŒá(Àlterms †°dONLNd    ¬àŒ•)publish±‡°dONLNd¬•Œ∫) and ü°dONLNd¬ªŒ‡)    subscribe◊¿°dONLNd¬‡Œå)%' to describe the Edition Manager featur{`°dONLNdE¬çŒò)≠es.
  7758. °dONLNdˇˇ)u
  7759. °dONLNd]‘l‡(›l+Each edition has an icon that is visible fr°dONLNdà‘‡\)≤
  7760. om the Finder®`°dONLNdï‘[‡`)=. ®`°dONLNdó‘`‡x)Figur{ °dONLNdú‘x‡å)e 1-1†°dONLNd°‘燇) shows the default °dONLNdµ‡lÏ•(Èledition icon. 
  7761. *!¯4* ¯"*_
  7762. ˇ·ˇ‚7^
  7763.     °dONLNdˇˇ*$
  7764. Figure 1-1°dONLNdƒÆ )BThe default edition icon
  7765. °dONLNd›\lh(elThe name that the user specifiÿ°dONLNd˚\hŸ)Ñ9es for the edition is located next to the edition icon. Tw@°dONLNd4\Ÿh‡)Èo °dONLNd6hltt(qlcrµ@°dONLNd8htt⁄)Seate customized edition icons, see the Finder Interface chapter in this volume for °dONLNdãtlÄÃ(}ldetailed information. ô@°dONLNd°tÃĉ)`Figurl°dONLNd¶t‰į)e 1-2    Ä°dONLNd´t˘Ä‡)5 illustrates a document containing a single publishera†°dONLNd‡tflÄ)Ê, its °dONLNdÊÄlå}(âlcorr`°dONLNdÍÄ~å∫)Gesponding edition, and a subscriber to the edition in another document.
  7766.  lE¯4 lD¯
  7767. !mDè
  7768. .#"#"(!}ma"Ö!Ém"Dè"!m†æ†éê#"#"!mDè?ÚUUPuÁ
  7769. ú0≠.8≠
  7770. ú‚g èÄ8"?¸ ß"/ Ô‚∫ÄnˇÄí?Ú^?Δ
  7771. ™™™≠-@?ΔÄèÄ/.m∞≠Zí¯ (∫í¿?<Zú∏?¸Ô?¸è≠0.u†è†éê#"#"!mDèUUPú0?ˇ8ú‚ 2Ä8" 0."=∫ ‚0.Ä=∫ˇÄ=∫=º-n-n
  7772. ™™™-nÆ?ÙÄ(Äm∞êZí¯
  7773. ∫í¿Zú∏=fl?ˇ‰S=⁄?ˇ†è°d
  7774. ONLNfò"ˇ°¿,/dstR[newpath clippath pathbbox]def newpath
  7775. °¿ dstR 0 get dstR 1 get translate
  7776. °¿*dstR 2 get dstR 0 get sub 354 320 sub div
  7777. °¿0dstR 3 get dstR 1 get sub 529 564 sub div scale
  7778. °¿320 neg 564 neg translate
  7779. °¿;%%BeginProcSet: FreeHand_header 2 0
  7780. /FreeHandDict 200 dict def
  7781. FreeHandDict begin
  7782. /currentpacking where{pop true setpacking}if
  7783. /bdf{bind def}bind def
  7784. /bdef{bind def}bdf
  7785. /xdf{exch def}bdf
  7786. /ndf{1 index where{pop pop pop}{dup xcheck{bind}if def}ifelse}bdf
  7787. /min{2 copy gt{exch}if pop}bdf
  7788. /max{2 copy lt{exch}if pop}bdf
  7789. °¿/graystep .01 def
  7790. °¿†/bottom -0 def
  7791. /delta -0 def
  7792. /frac -0 def
  7793. /left -0 def
  7794. /numsteps -0 def
  7795. /numsteps1 -0 def
  7796. /radius -0 def
  7797. /right -0 def
  7798. /top -0 def
  7799. /x -0 def
  7800. /y -0 def
  7801. /df currentflat def
  7802. /tempstr 1 string def
  7803. /clipflatness 3 def
  7804. /inverted?
  7805. 0 currenttransfer exec .5 ge def
  7806. /concatprocs{
  7807. /proc2 exch cvlit def/proc1 exch cvlit def
  7808. /newproc proc1 length proc2 length add array def
  7809. newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval
  7810. newproc cvx}bdf
  7811. /storerect{/top xdf/right xdf/bottom xdf/left xdf}bdf
  7812. /rectpath{newpath left bottom moveto left top lineto
  7813. right top lineto right bottom lineto closepath}bdf
  7814. /sf{dup 0 eq{pop df dup 3 mul}{dup} ifelse /clipflatness xdf setflat}bdf
  7815. version cvr 38.0 le
  7816. {/setrgbcolor{
  7817. currenttransfer exec 3 1 roll
  7818. currenttransfer exec 3 1 roll
  7819. currenttransfer exec 3 1 roll
  7820. setrgbcolor}bdf}if
  7821. /gettint{0 get}bdf
  7822. /puttint{0 exch put}bdf
  7823. /vms{/vmsv save def}bdf
  7824. /vmr{vmsv restore}bdf
  7825. /vmrs{vmr vms}bdf
  7826. °¿…/CD{/NF exch def
  7827. {exch dup/FID ne{exch NF 3 1 roll put}
  7828. {pop pop}ifelse}forall NF}bdf
  7829. /MN{1 index length/Len exch def
  7830. dup length Len add string dup
  7831. Len 4 -1 roll putinterval dup 0 4 -1 roll putinterval}bdf
  7832. /RC{256 string cvs(|______)anchorsearch
  7833. {1 index MN cvn/NewN exch def cvn
  7834. findfont dup maxlength dict CD dup/FontName NewN put dup
  7835. /Encoding MacVec put NewN exch definefont pop}{pop}ifelse}bdf
  7836. /RF{dup FontDirectory exch known{pop}{RC}ifelse}bdf
  7837. /FF{dup 256 string cvs(|______)exch MN cvn dup FontDirectory exch known
  7838. {exch}if pop findfont}bdf
  7839. userdict begin /BDFontDict 20 dict def end
  7840. BDFontDict begin
  7841. /bu{}def
  7842. /bn{}def
  7843. /setTxMode{pop}def
  7844. /gm{moveto}def
  7845. /show{pop}def
  7846. /gr{pop}def
  7847. /fnt{pop pop pop}def
  7848. /fs{pop}def
  7849. /fz{pop}def
  7850. /lin{pop pop}def
  7851. end
  7852. /MacVec 256 array def
  7853. MacVec 0 /Helvetica findfont
  7854. /Encoding get 0 128 getinterval putinterval
  7855. MacVec 127 /DEL put MacVec 16#27 /quotesingle put MacVec 16#60 /grave put
  7856. /NUL/SOH/STX/ETX/EOT/ENQ/ACK/BEL/BS/HT/LF/VT/FF/CR/SO/SI
  7857. /DLE/DC1/DC2/DC3/DC4/NAK/SYN/ETB/CAN/EM/SUB/ESC/FS/GS/RS/US
  7858. MacVec 0 32 getinterval astore pop
  7859. /Adieresis/Aring/Ccedilla/Eacute/Ntilde/Odieresis/Udieresis/aacute
  7860. /agrave/acircumflex/adieresis/atilde/aring/ccedilla/eacute/egrave
  7861. /ecircumflex/edieresis/iacute/igrave/icircumflex/idieresis/ntilde/oacute
  7862. /ograve/ocircumflex/odieresis/otilde/uacute/ugrave/ucircumflex/udieresis
  7863. /dagger/degree/cent/sterling/section/bullet/paragraph/germandbls
  7864. /register/copyright/trademark/acute/dieresis/notequal/AE/Oslash
  7865. /infinity/plusminus/lessequal/greaterequal/yen/mu/partialdiff/summation
  7866. /product/pi/integral/ordfeminine/ordmasculine/Omega/ae/oslash
  7867. /questiondown/exclamdown/logicalnot/radical/florin/approxequal/Delta/guillemotleft
  7868. /guillemotright/ellipsis/nbspace/Agrave/Atilde/Otilde/OE/oe
  7869. /endash/emdash/quotedblleft/quotedblright/quoteleft/quoteright/divide/lozenge
  7870. /ydieresis/Ydieresis/fraction/currency/guilsinglleft/guilsinglright/fi/fl
  7871. /daggerdbl/periodcentered/quotesinglbase/quotedblbase
  7872. /perthousand/Acircumflex/Ecircumflex/Aacute
  7873. /Edieresis/Egrave/Iacute/Icircumflex/Idieresis/Igrave/Oacute/Ocircumflex
  7874. /apple/Ograve/Uacute/Ucircumflex/Ugrave/dotlessi/circumflex/tilde
  7875. /macron/breve/dotaccent/ring/cedilla/hungarumlaut/ogonek/caron
  7876. MacVec 128 128 getinterval astore pop
  7877. °¿3/fps{currentflat exch dup 0 le{pop 1}if
  7878. {dup setflat 3 index stopped
  7879. {1.3 mul dup 3 index gt{pop setflat pop pop stop}if}{exit}ifelse
  7880. }loop pop setflat pop pop
  7881. }bdf
  7882. /fp{100 currentflat fps}bdf
  7883. /rfp{clipflatness currentflat fps}bdf
  7884. /fcp{100 clipflatness fps}bdf
  7885. /fclip{{clip}fcp}bdf
  7886. /feoclip{{eoclip}fcp}bdf
  7887. °¿Aend %. FreeHandDict
  7888. %%EndProcSet
  7889. %%BeginSetup
  7890. FreeHandDict begin
  7891. °¿∑/ccmyk{dup 5 -1 roll sub 0 max exch}ndf
  7892. /setcmykcolor{1 exch sub ccmyk ccmyk ccmyk pop setrgbcolor}ndf
  7893. /setcmykcoloroverprint{4{dup -1 eq{pop 0}if 4 1 roll}repeat setcmykcolor}ndf
  7894. /findcmykcustomcolor{5 /packedarray where{pop packedarray}{array astore readonly}ifelse}ndf
  7895. /setcustomcolor{exch aload pop pop 4{4 index mul 4 1 roll}repeat setcmykcolor pop}ndf
  7896. /setseparationgray{1 exch sub dup dup dup setcmykcolor}ndf
  7897. /setoverprint{pop}ndf
  7898. /currentoverprint false ndf
  7899. /colorimage{pop pop
  7900. [5 -1 roll/exec cvx 6 -1 roll/exec cvx 7 -1 roll/exec cvx 8 -1 roll/exec cvx
  7901. /exch cvx/pop cvx/exch cvx/pop cvx/exch cvx/pop cvx/invbuf cvx]cvx image}
  7902. %. version 47.1 of Postscript defines colorimage incorrectly (rgb model only)
  7903. version cvr 47.1 le{userdict begin bdf end}{ndf}ifelse
  7904. /customcolorimage{pop image}ndf
  7905. /separationimage{image}ndf
  7906. /newcmykcustomcolor{6 /packedarray where{pop packedarray}{array astore readonly}ifelse}ndf
  7907. /inkoverprint false ndf
  7908. /setinkoverprint{pop}ndf
  7909. /overprintprocess{pop}ndf
  7910. /setspotcolor
  7911. {spots exch get 0 5 getinterval exch setcustomcolor}ndf
  7912. /currentcolortransfer{currenttransfer dup dup dup}ndf
  7913. /setcolortransfer{systemdict begin settransfer end pop pop pop}ndf
  7914. /setimagecmyk{dup length 4 eq
  7915. {aload pop}
  7916. {aload pop spots exch get 0 4 getinterval aload pop 4
  7917. {4 index mul 4 1 roll}repeat 5 -1 roll pop} ifelse
  7918. systemdict /colorimage known{version cvr 47.1 gt}{false}ifelse
  7919. not{pop 1 currentgray sub}if
  7920. /ik xdf /iy xdf /im xdf /ic xdf
  7921. }ndf
  7922. °¿ã/setcolor{dup length 4 eq
  7923. {aload overprintprocess setcmykcolor}
  7924. {aload 1 get spots exch get 5 get setinkoverprint setspotcolor}
  7925. ifelse}ndf
  7926. °¿j/bc2[0 0]def
  7927. /bc4[0 0 0 0]def
  7928. /c1[0 0 0 0]def
  7929. /c2[0 0 0 0]def
  7930. /absmax{2 copy abs exch abs gt{exch}if pop}bdf
  7931. /calcstep
  7932. {c1 length 4 eq
  7933. {
  7934. 0 1 3
  7935. {c1 1 index get
  7936. c2 3 -1 roll get
  7937. sub
  7938. }for
  7939. absmax absmax absmax
  7940. }
  7941. {
  7942. bc2 c1 1 get 1 exch put
  7943. c1 gettint c2 gettint
  7944. sub abs
  7945. }ifelse
  7946. graystep div abs round dup 0 eq{pop 1}if
  7947. dup /numsteps xdf 1 sub dup 0 eq{pop 1}if /numsteps1 xdf
  7948. }bdf
  7949. /cblend{
  7950. c1 length 4 eq
  7951. {
  7952. 0 1 3
  7953. {bc4 exch
  7954. c1 1 index get
  7955. c2 2 index get
  7956. 1 index sub
  7957. frac mul add put
  7958. }for bc4
  7959. }{
  7960. bc2
  7961. c1 gettint
  7962. c2 gettint
  7963. 1 index sub
  7964. frac mul add
  7965. puttint bc2
  7966. }ifelse
  7967. setcolor
  7968. }bdf
  7969. /logtaper{/frac frac 9 mul 1 add log def}bdf
  7970. °¿Ü/imbits 1 def
  7971. /iminv false def
  7972. /invbuf{0 1 2 index length 1 sub{dup 2 index exch get 255 exch sub 2 index 3 1 roll put}for}bdf
  7973. /cyanrp{currentfile cyanbuf readhexstring pop iminv{invbuf}if}def
  7974. /magentarp{cyanbuf magentabuf copy}bdf
  7975. /yellowrp{cyanbuf yellowbuf copy}bdf
  7976. /blackrp{cyanbuf blackbuf copy}bdf
  7977. /fixtransfer{
  7978. dup{ic mul ic sub 1 add}concatprocs exch
  7979. dup{im mul im sub 1 add}concatprocs exch
  7980. dup{iy mul iy sub 1 add}concatprocs exch
  7981. {ik mul ik sub 1 add}concatprocs
  7982. currentcolortransfer
  7983. 5 -1 roll exch concatprocs 7 1 roll
  7984. 4 -1 roll exch concatprocs 6 1 roll
  7985. 3 -1 roll exch concatprocs 5 1 roll
  7986. concatprocs 4 1 roll
  7987. setcolortransfer
  7988. }bdf
  7989. †¿°¿+/textopf false def
  7990. /curtextmtx{}def
  7991. /otw .25 def
  7992. /msf{dup/curtextmtx xdf makefont setfont}bdf
  7993. /makesetfont/msf load def
  7994. /curtextheight{.707104 .707104 curtextmtx dtransform
  7995. dup mul exch dup mul add sqrt}bdf
  7996. /ta{1 index
  7997. {tempstr 0 2 index put tempstr 2 index
  7998. gsave exec grestore
  7999. tempstr stringwidth rmoveto
  8000. 5 index eq{6 index 6 index rmoveto}if
  8001. 3 index 3 index rmoveto
  8002. }forall 7{pop}repeat}bdf
  8003. /sts{setcolor textopf setoverprint/ts{awidthshow}def exec}bdf
  8004. /stol{setlinewidth setcolor textopf setoverprint newpath
  8005. /ts{{false charpath stroke}ta}def exec}bdf
  8006. °¿./currentpacking where{pop false setpacking}if
  8007. °¿ %%EndSetup
  8008. °¿/f0 /Symbol FF def
  8009. °¿*/f1 /|______Helvetica dup RF findfont def
  8010. °¿7/spots[1 0 0 0 (Process Cyan) false newcmykcustomcolor
  8011. °¿30 1 0 0 (Process Magenta) false newcmykcustomcolor
  8012. °¿20 0 1 0 (Process Yellow) false newcmykcustomcolor
  8013. °¿10 0 0 1 (Process Black) false newcmykcustomcolor
  8014. °¿]def
  8015. °¿vms
  8016. °¿gsave [1 0 0 1 0 0] concat
  8017. °¿vms
  8018. °¿3°¿ sf
  8019. °¿newpath
  8020. °¿337.5 °¿558.9 °¿moveto
  8021. °¿338.4 °¿558.9 °¿lineto
  8022. °¿338.4 °¿558 °¿lineto
  8023. °¿337.5 °¿558 °¿lineto
  8024. °¿
  8025. closepath
  8026. °¿gsave
  8027. °¿[0 0 0 1]setcolor  {fill}fp 
  8028. °¿    grestore
  8029. °¿3°¿ sf
  8030. °¿newpath
  8031. °¿341.5 °¿558.9 °¿moveto
  8032. °¿342.4 °¿558.9 °¿lineto
  8033. °¿342.4 °¿558 °¿lineto
  8034. °¿341.5 °¿558 °¿lineto
  8035. °¿
  8036. closepath
  8037. °¿gsave
  8038. °¿[0 0 0 1]setcolor  {fill}fp 
  8039. °¿    grestore
  8040. °¿3°¿ sf
  8041. °¿newpath
  8042. °¿337.5 °¿554.9 °¿moveto
  8043. °¿338.4 °¿554.9 °¿lineto
  8044. °¿338.4 °¿554 °¿lineto
  8045. °¿337.5 °¿554 °¿lineto
  8046. °¿
  8047. closepath
  8048. °¿gsave
  8049. °¿[0 0 0 1]setcolor  {fill}fp 
  8050. °¿    grestore
  8051. °¿3°¿ sf
  8052. °¿newpath
  8053. °¿341.5 °¿554.9 °¿moveto
  8054. °¿342.4 °¿554.9 °¿lineto
  8055. °¿342.4 °¿554 °¿lineto
  8056. °¿341.5 °¿554 °¿lineto
  8057. °¿
  8058. closepath
  8059. °¿gsave
  8060. °¿[0 0 0 1]setcolor  {fill}fp 
  8061. °¿    grestore
  8062. °¿3°¿ sf
  8063. °¿newpath
  8064. °¿338.5 °¿560 °¿moveto
  8065. °¿341.4 °¿560 °¿lineto
  8066. °¿341.4 °¿559.1 °¿lineto
  8067. °¿338.5 °¿559.1 °¿lineto
  8068. °¿
  8069. closepath
  8070. °¿gsave
  8071. °¿[0 0 0 1]setcolor  {fill}fp 
  8072. °¿    grestore
  8073. °¿3°¿ sf
  8074. °¿newpath
  8075. °¿336.5 °¿557.9 °¿moveto
  8076. °¿337.4 °¿557.9 °¿lineto
  8077. °¿337.4 °¿555.1 °¿lineto
  8078. °¿336.5 °¿555.1 °¿lineto
  8079. °¿
  8080. closepath
  8081. °¿gsave
  8082. °¿[0 0 0 1]setcolor  {fill}fp 
  8083. °¿    grestore
  8084. °¿3°¿ sf
  8085. °¿newpath
  8086. °¿342.6 °¿557.9 °¿moveto
  8087. °¿343.4 °¿557.9 °¿lineto
  8088. °¿343.4 °¿555.9 °¿lineto
  8089. °¿347.5 °¿555.9 °¿lineto
  8090. °¿347.5 °¿549 °¿lineto
  8091. °¿340.5 °¿549 °¿lineto
  8092. °¿340.5 °¿553 °¿lineto
  8093. °¿338.5 °¿553 °¿lineto
  8094. °¿338.5 °¿553.9 °¿lineto
  8095. °¿341.5 °¿553.9 °¿lineto
  8096. °¿341.5 °¿549.9 °¿lineto
  8097. °¿346.6 °¿549.9 °¿lineto
  8098. °¿346.6 °¿555 °¿lineto
  8099. °¿342.6 °¿555 °¿lineto
  8100. °¿342.6 °¿557.9 °¿lineto
  8101. °¿
  8102. closepath
  8103. °¿gsave
  8104. °¿[0 0 0 1]setcolor  {fill}fp 
  8105. °¿    grestore
  8106. °¿3°¿ sf
  8107. °¿newpath
  8108. °¿322.5 °¿564 °¿moveto
  8109. °¿323.4 °¿564 °¿lineto
  8110. °¿323.4 °¿563.1 °¿lineto
  8111. °¿322.5 °¿563.1 °¿lineto
  8112. °¿
  8113. closepath
  8114. °¿gsave
  8115. °¿[0 0 0 1]setcolor  {fill}fp 
  8116. °¿    grestore
  8117. °¿3°¿ sf
  8118. °¿newpath
  8119. °¿323.6 °¿562.9 °¿moveto
  8120. °¿324.5 °¿562.9 °¿lineto
  8121. °¿324.5 °¿562 °¿lineto
  8122. °¿323.6 °¿562 °¿lineto
  8123. °¿
  8124. closepath
  8125. °¿gsave
  8126. °¿[0 0 0 1]setcolor  {fill}fp 
  8127. °¿    grestore
  8128. °¿3°¿ sf
  8129. °¿newpath
  8130. °¿324.5 °¿564 °¿moveto
  8131. °¿325.4 °¿564 °¿lineto
  8132. °¿325.4 °¿563.1 °¿lineto
  8133. °¿324.5 °¿563.1 °¿lineto
  8134. °¿
  8135. closepath
  8136. °¿gsave
  8137. °¿[0 0 0 1]setcolor  {fill}fp 
  8138. °¿    grestore
  8139. °¿3°¿ sf
  8140. °¿newpath
  8141. °¿325.6 °¿562.9 °¿moveto
  8142. °¿326.5 °¿562.9 °¿lineto
  8143. °¿326.5 °¿562 °¿lineto
  8144. °¿325.6 °¿562 °¿lineto
  8145. °¿
  8146. closepath
  8147. °¿gsave
  8148. °¿[0 0 0 1]setcolor  {fill}fp 
  8149. °¿    grestore
  8150. °¿3°¿ sf
  8151. °¿newpath
  8152. °¿326.5 °¿564 °¿moveto
  8153. °¿327.4 °¿564 °¿lineto
  8154. °¿327.4 °¿563.1 °¿lineto
  8155. °¿326.5 °¿563.1 °¿lineto
  8156. °¿
  8157. closepath
  8158. °¿gsave
  8159. °¿[0 0 0 1]setcolor  {fill}fp 
  8160. °¿    grestore
  8161. °¿3°¿ sf
  8162. °¿newpath
  8163. °¿327.6 °¿562.9 °¿moveto
  8164. °¿328.5 °¿562.9 °¿lineto
  8165. °¿328.5 °¿562 °¿lineto
  8166. °¿327.6 °¿562 °¿lineto
  8167. °¿
  8168. closepath
  8169. °¿gsave
  8170. °¿[0 0 0 1]setcolor  {fill}fp 
  8171. °¿    grestore
  8172. °¿3°¿ sf
  8173. °¿newpath
  8174. °¿328.5 °¿564 °¿moveto
  8175. °¿329.4 °¿564 °¿lineto
  8176. °¿329.4 °¿563.1 °¿lineto
  8177. °¿328.5 °¿563.1 °¿lineto
  8178. °¿
  8179. closepath
  8180. °¿gsave
  8181. °¿[0 0 0 1]setcolor  {fill}fp 
  8182. °¿    grestore
  8183. °¿3°¿ sf
  8184. °¿newpath
  8185. °¿329.6 °¿562.9 °¿moveto
  8186. °¿330.5 °¿562.9 °¿lineto
  8187. °¿330.5 °¿562 °¿lineto
  8188. °¿329.6 °¿562 °¿lineto
  8189. °¿
  8190. closepath
  8191. °¿gsave
  8192. °¿[0 0 0 1]setcolor  {fill}fp 
  8193. °¿    grestore
  8194. °¿3°¿ sf
  8195. °¿newpath
  8196. °¿330.5 °¿564 °¿moveto
  8197. °¿331.4 °¿564 °¿lineto
  8198. °¿331.4 °¿563.1 °¿lineto
  8199. °¿330.5 °¿563.1 °¿lineto
  8200. °¿
  8201. closepath
  8202. °¿gsave
  8203. °¿[0 0 0 1]setcolor  {fill}fp 
  8204. °¿    grestore
  8205. °¿3°¿ sf
  8206. °¿newpath
  8207. °¿331.6 °¿562.9 °¿moveto
  8208. °¿332.5 °¿562.9 °¿lineto
  8209. °¿332.5 °¿562 °¿lineto
  8210. °¿331.6 °¿562 °¿lineto
  8211. °¿
  8212. closepath
  8213. °¿gsave
  8214. °¿[0 0 0 1]setcolor  {fill}fp 
  8215. °¿    grestore
  8216. °¿3°¿ sf
  8217. °¿newpath
  8218. °¿332.5 °¿564 °¿moveto
  8219. °¿333.4 °¿564 °¿lineto
  8220. °¿333.4 °¿563.1 °¿lineto
  8221. °¿332.5 °¿563.1 °¿lineto
  8222. °¿
  8223. closepath
  8224. °¿gsave
  8225. °¿[0 0 0 1]setcolor  {fill}fp 
  8226. °¿    grestore
  8227. °¿3°¿ sf
  8228. °¿newpath
  8229. °¿333.6 °¿562.9 °¿moveto
  8230. °¿334.5 °¿562.9 °¿lineto
  8231. °¿334.5 °¿562 °¿lineto
  8232. °¿333.6 °¿562 °¿lineto
  8233. °¿
  8234. closepath
  8235. °¿gsave
  8236. °¿[0 0 0 1]setcolor  {fill}fp 
  8237. °¿    grestore
  8238. °¿3°¿ sf
  8239. °¿newpath
  8240. °¿334.5 °¿564 °¿moveto
  8241. °¿335.4 °¿564 °¿lineto
  8242. °¿335.4 °¿563.1 °¿lineto
  8243. °¿334.5 °¿563.1 °¿lineto
  8244. °¿
  8245. closepath
  8246. °¿gsave
  8247. °¿[0 0 0 1]setcolor  {fill}fp 
  8248. °¿    grestore
  8249. °¿vmrs
  8250. °¿3°¿ sf
  8251. °¿newpath
  8252. °¿335.6 °¿562.9 °¿moveto
  8253. °¿336.5 °¿562.9 °¿lineto
  8254. °¿336.5 °¿562 °¿lineto
  8255. °¿335.6 °¿562 °¿lineto
  8256. °¿
  8257. closepath
  8258. °¿gsave
  8259. °¿[0 0 0 1]setcolor  {fill}fp 
  8260. °¿    grestore
  8261. °¿3°¿ sf
  8262. °¿newpath
  8263. °¿336.5 °¿564 °¿moveto
  8264. °¿337.4 °¿564 °¿lineto
  8265. °¿337.4 °¿563.1 °¿lineto
  8266. °¿336.5 °¿563.1 °¿lineto
  8267. °¿
  8268. closepath
  8269. °¿gsave
  8270. °¿[0 0 0 1]setcolor  {fill}fp 
  8271. °¿    grestore
  8272. °¿3°¿ sf
  8273. °¿newpath
  8274. °¿337.6 °¿562.9 °¿moveto
  8275. °¿338.5 °¿562.9 °¿lineto
  8276. °¿338.5 °¿562 °¿lineto
  8277. °¿337.6 °¿562 °¿lineto
  8278. °¿
  8279. closepath
  8280. °¿gsave
  8281. °¿[0 0 0 1]setcolor  {fill}fp 
  8282. °¿    grestore
  8283. °¿3°¿ sf
  8284. °¿newpath
  8285. °¿338.5 °¿564 °¿moveto
  8286. °¿339.4 °¿564 °¿lineto
  8287. °¿339.4 °¿563.1 °¿lineto
  8288. °¿338.5 °¿563.1 °¿lineto
  8289. °¿
  8290. closepath
  8291. °¿gsave
  8292. °¿[0 0 0 1]setcolor  {fill}fp 
  8293. °¿    grestore
  8294. °¿3°¿ sf
  8295. °¿newpath
  8296. °¿339.6 °¿562.9 °¿moveto
  8297. °¿340.5 °¿562.9 °¿lineto
  8298. °¿340.5 °¿562 °¿lineto
  8299. °¿339.6 °¿562 °¿lineto
  8300. °¿
  8301. closepath
  8302. °¿gsave
  8303. °¿[0 0 0 1]setcolor  {fill}fp 
  8304. °¿    grestore
  8305. °¿3°¿ sf
  8306. °¿newpath
  8307. °¿340.5 °¿564 °¿moveto
  8308. °¿341.4 °¿564 °¿lineto
  8309. °¿341.4 °¿563.1 °¿lineto
  8310. °¿340.5 °¿563.1 °¿lineto
  8311. °¿
  8312. closepath
  8313. °¿gsave
  8314. °¿[0 0 0 1]setcolor  {fill}fp 
  8315. °¿    grestore
  8316. °¿3°¿ sf
  8317. °¿newpath
  8318. °¿341.6 °¿562.9 °¿moveto
  8319. °¿342.5 °¿562.9 °¿lineto
  8320. °¿342.5 °¿562 °¿lineto
  8321. °¿341.6 °¿562 °¿lineto
  8322. °¿
  8323. closepath
  8324. °¿gsave
  8325. °¿[0 0 0 1]setcolor  {fill}fp 
  8326. °¿    grestore
  8327. °¿3°¿ sf
  8328. °¿newpath
  8329. °¿342.5 °¿564 °¿moveto
  8330. °¿343.4 °¿564 °¿lineto
  8331. °¿343.4 °¿563.1 °¿lineto
  8332. °¿342.5 °¿563.1 °¿lineto
  8333. °¿
  8334. closepath
  8335. °¿gsave
  8336. °¿[0 0 0 1]setcolor  {fill}fp 
  8337. °¿    grestore
  8338. °¿3°¿ sf
  8339. °¿newpath
  8340. °¿343.6 °¿562.9 °¿moveto
  8341. °¿344.5 °¿562.9 °¿lineto
  8342. °¿344.5 °¿562 °¿lineto
  8343. °¿343.6 °¿562 °¿lineto
  8344. °¿
  8345. closepath
  8346. °¿gsave
  8347. °¿[0 0 0 1]setcolor  {fill}fp 
  8348. °¿    grestore
  8349. °¿3°¿ sf
  8350. °¿newpath
  8351. °¿344.5 °¿564 °¿moveto
  8352. °¿345.4 °¿564 °¿lineto
  8353. °¿345.4 °¿563.1 °¿lineto
  8354. °¿344.5 °¿563.1 °¿lineto
  8355. °¿
  8356. closepath
  8357. °¿gsave
  8358. °¿[0 0 0 1]setcolor  {fill}fp 
  8359. °¿    grestore
  8360. °¿3°¿ sf
  8361. °¿newpath
  8362. °¿345.6 °¿562.9 °¿moveto
  8363. °¿346.5 °¿562.9 °¿lineto
  8364. °¿346.5 °¿562 °¿lineto
  8365. °¿345.6 °¿562 °¿lineto
  8366. °¿
  8367. closepath
  8368. °¿gsave
  8369. °¿[0 0 0 1]setcolor  {fill}fp 
  8370. °¿    grestore
  8371. °¿3°¿ sf
  8372. °¿newpath
  8373. °¿346.5 °¿564 °¿moveto
  8374. °¿347.4 °¿564 °¿lineto
  8375. °¿347.4 °¿563.1 °¿lineto
  8376. °¿346.5 °¿563.1 °¿lineto
  8377. °¿
  8378. closepath
  8379. °¿gsave
  8380. °¿[0 0 0 1]setcolor  {fill}fp 
  8381. °¿    grestore
  8382. °¿3°¿ sf
  8383. °¿newpath
  8384. °¿347.6 °¿562.9 °¿moveto
  8385. °¿348.5 °¿562.9 °¿lineto
  8386. °¿348.5 °¿562 °¿lineto
  8387. °¿347.6 °¿562 °¿lineto
  8388. °¿
  8389. closepath
  8390. °¿gsave
  8391. °¿[0 0 0 1]setcolor  {fill}fp 
  8392. °¿    grestore
  8393. °¿3°¿ sf
  8394. °¿newpath
  8395. °¿348.5 °¿564 °¿moveto
  8396. °¿349.4 °¿564 °¿lineto
  8397. °¿349.4 °¿563.1 °¿lineto
  8398. °¿348.5 °¿563.1 °¿lineto
  8399. °¿
  8400. closepath
  8401. °¿gsave
  8402. °¿[0 0 0 1]setcolor  {fill}fp 
  8403. °¿    grestore
  8404. °¿3°¿ sf
  8405. °¿newpath
  8406. °¿324.6 °¿543.9 °¿moveto
  8407. °¿325.5 °¿543.9 °¿lineto
  8408. °¿325.5 °¿543 °¿lineto
  8409. °¿324.6 °¿543 °¿lineto
  8410. °¿
  8411. closepath
  8412. °¿gsave
  8413. °¿[0 0 0 1]setcolor  {fill}fp 
  8414. °¿    grestore
  8415. °¿3°¿ sf
  8416. °¿newpath
  8417. °¿325.5 °¿545 °¿moveto
  8418. °¿326.4 °¿545 °¿lineto
  8419. °¿326.4 °¿544.1 °¿lineto
  8420. °¿325.5 °¿544.1 °¿lineto
  8421. °¿
  8422. closepath
  8423. °¿gsave
  8424. °¿[0 0 0 1]setcolor  {fill}fp 
  8425. °¿    grestore
  8426. °¿3°¿ sf
  8427. °¿newpath
  8428. °¿326.6 °¿543.9 °¿moveto
  8429. °¿327.5 °¿543.9 °¿lineto
  8430. °¿327.5 °¿543 °¿lineto
  8431. °¿326.6 °¿543 °¿lineto
  8432. °¿
  8433. closepath
  8434. °¿gsave
  8435. °¿[0 0 0 1]setcolor  {fill}fp 
  8436. °¿    grestore
  8437. °¿3°¿ sf
  8438. °¿newpath
  8439. °¿327.5 °¿545 °¿moveto
  8440. °¿328.4 °¿545 °¿lineto
  8441. °¿328.4 °¿544.1 °¿lineto
  8442. °¿327.5 °¿544.1 °¿lineto
  8443. °¿
  8444. closepath
  8445. °¿gsave
  8446. °¿[0 0 0 1]setcolor  {fill}fp 
  8447. °¿    grestore
  8448. °¿3°¿ sf
  8449. °¿newpath
  8450. °¿328.6 °¿543.9 °¿moveto
  8451. °¿329.5 °¿543.9 °¿lineto
  8452. °¿329.5 °¿543 °¿lineto
  8453. °¿328.6 °¿543 °¿lineto
  8454. °¿
  8455. closepath
  8456. °¿gsave
  8457. °¿[0 0 0 1]setcolor  {fill}fp 
  8458. °¿    grestore
  8459. °¿3°¿ sf
  8460. °¿newpath
  8461. °¿329.5 °¿545 °¿moveto
  8462. °¿330.4 °¿545 °¿lineto
  8463. °¿330.4 °¿544.1 °¿lineto
  8464. °¿329.5 °¿544.1 °¿lineto
  8465. °¿
  8466. closepath
  8467. °¿gsave
  8468. °¿[0 0 0 1]setcolor  {fill}fp 
  8469. °¿    grestore
  8470. °¿vmrs
  8471. °¿3°¿ sf
  8472. °¿newpath
  8473. °¿330.6 °¿543.9 °¿moveto
  8474. °¿331.5 °¿543.9 °¿lineto
  8475. °¿331.5 °¿543 °¿lineto
  8476. °¿330.6 °¿543 °¿lineto
  8477. °¿
  8478. closepath
  8479. °¿gsave
  8480. °¿[0 0 0 1]setcolor  {fill}fp 
  8481. °¿    grestore
  8482. °¿3°¿ sf
  8483. °¿newpath
  8484. °¿331.5 °¿545 °¿moveto
  8485. °¿332.4 °¿545 °¿lineto
  8486. °¿332.4 °¿544.1 °¿lineto
  8487. °¿331.5 °¿544.1 °¿lineto
  8488. °¿
  8489. closepath
  8490. °¿gsave
  8491. °¿[0 0 0 1]setcolor  {fill}fp 
  8492. °¿    grestore
  8493. °¿3°¿ sf
  8494. °¿newpath
  8495. °¿332.6 °¿543.9 °¿moveto
  8496. °¿333.5 °¿543.9 °¿lineto
  8497. °¿333.5 °¿543 °¿lineto
  8498. °¿332.6 °¿543 °¿lineto
  8499. °¿
  8500. closepath
  8501. °¿gsave
  8502. °¿[0 0 0 1]setcolor  {fill}fp 
  8503. °¿    grestore
  8504. °¿3°¿ sf
  8505. °¿newpath
  8506. °¿333.5 °¿545 °¿moveto
  8507. °¿334.4 °¿545 °¿lineto
  8508. °¿334.4 °¿544.1 °¿lineto
  8509. °¿333.5 °¿544.1 °¿lineto
  8510. °¿
  8511. closepath
  8512. °¿gsave
  8513. °¿[0 0 0 1]setcolor  {fill}fp 
  8514. °¿    grestore
  8515. °¿3°¿ sf
  8516. °¿newpath
  8517. °¿334.6 °¿543.9 °¿moveto
  8518. °¿335.5 °¿543.9 °¿lineto
  8519. °¿335.5 °¿543 °¿lineto
  8520. °¿334.6 °¿543 °¿lineto
  8521. °¿
  8522. closepath
  8523. °¿gsave
  8524. °¿[0 0 0 1]setcolor  {fill}fp 
  8525. °¿    grestore
  8526. °¿3°¿ sf
  8527. °¿newpath
  8528. °¿335.5 °¿545 °¿moveto
  8529. °¿336.4 °¿545 °¿lineto
  8530. °¿336.4 °¿544.1 °¿lineto
  8531. °¿335.5 °¿544.1 °¿lineto
  8532. °¿
  8533. closepath
  8534. °¿gsave
  8535. °¿[0 0 0 1]setcolor  {fill}fp 
  8536. °¿    grestore
  8537. °¿3°¿ sf
  8538. °¿newpath
  8539. °¿336.6 °¿543.9 °¿moveto
  8540. °¿337.5 °¿543.9 °¿lineto
  8541. °¿337.5 °¿543 °¿lineto
  8542. °¿336.6 °¿543 °¿lineto
  8543. °¿
  8544. closepath
  8545. °¿gsave
  8546. °¿[0 0 0 1]setcolor  {fill}fp 
  8547. °¿    grestore
  8548. °¿3°¿ sf
  8549. °¿newpath
  8550. °¿337.5 °¿545 °¿moveto
  8551. °¿338.4 °¿545 °¿lineto
  8552. °¿338.4 °¿544.1 °¿lineto
  8553. °¿337.5 °¿544.1 °¿lineto
  8554. °¿
  8555. closepath
  8556. °¿gsave
  8557. °¿[0 0 0 1]setcolor  {fill}fp 
  8558. °¿    grestore
  8559. °¿3°¿ sf
  8560. °¿newpath
  8561. °¿338.6 °¿543.9 °¿moveto
  8562. °¿339.5 °¿543.9 °¿lineto
  8563. °¿339.5 °¿543 °¿lineto
  8564. °¿338.6 °¿543 °¿lineto
  8565. °¿
  8566. closepath
  8567. °¿gsave
  8568. °¿[0 0 0 1]setcolor  {fill}fp 
  8569. °¿    grestore
  8570. °¿3°¿ sf
  8571. °¿newpath
  8572. °¿339.5 °¿545 °¿moveto
  8573. °¿340.4 °¿545 °¿lineto
  8574. °¿340.4 °¿544.1 °¿lineto
  8575. °¿339.5 °¿544.1 °¿lineto
  8576. °¿
  8577. closepath
  8578. °¿gsave
  8579. °¿[0 0 0 1]setcolor  {fill}fp 
  8580. °¿    grestore
  8581. °¿3°¿ sf
  8582. °¿newpath
  8583. °¿340.6 °¿543.9 °¿moveto
  8584. °¿341.5 °¿543.9 °¿lineto
  8585. °¿341.5 °¿543 °¿lineto
  8586. °¿340.6 °¿543 °¿lineto
  8587. °¿
  8588. closepath
  8589. °¿gsave
  8590. °¿[0 0 0 1]setcolor  {fill}fp 
  8591. °¿    grestore
  8592. °¿3°¿ sf
  8593. °¿newpath
  8594. °¿341.5 °¿545 °¿moveto
  8595. °¿342.4 °¿545 °¿lineto
  8596. °¿342.4 °¿544.1 °¿lineto
  8597. °¿341.5 °¿544.1 °¿lineto
  8598. °¿
  8599. closepath
  8600. °¿gsave
  8601. °¿[0 0 0 1]setcolor  {fill}fp 
  8602. °¿    grestore
  8603. °¿3°¿ sf
  8604. °¿newpath
  8605. °¿342.6 °¿543.9 °¿moveto
  8606. °¿343.5 °¿543.9 °¿lineto
  8607. °¿343.5 °¿543 °¿lineto
  8608. °¿342.6 °¿543 °¿lineto
  8609. °¿
  8610. closepath
  8611. °¿gsave
  8612. °¿[0 0 0 1]setcolor  {fill}fp 
  8613. °¿    grestore
  8614. °¿3°¿ sf
  8615. °¿newpath
  8616. °¿343.5 °¿545 °¿moveto
  8617. °¿344.4 °¿545 °¿lineto
  8618. °¿344.4 °¿544.1 °¿lineto
  8619. °¿343.5 °¿544.1 °¿lineto
  8620. °¿
  8621. closepath
  8622. °¿gsave
  8623. °¿[0 0 0 1]setcolor  {fill}fp 
  8624. °¿    grestore
  8625. °¿3°¿ sf
  8626. °¿newpath
  8627. °¿344.6 °¿543.9 °¿moveto
  8628. °¿345.5 °¿543.9 °¿lineto
  8629. °¿345.5 °¿543 °¿lineto
  8630. °¿344.6 °¿543 °¿lineto
  8631. °¿
  8632. closepath
  8633. °¿gsave
  8634. °¿[0 0 0 1]setcolor  {fill}fp 
  8635. °¿    grestore
  8636. °¿3°¿ sf
  8637. °¿newpath
  8638. °¿345.5 °¿545 °¿moveto
  8639. °¿346.4 °¿545 °¿lineto
  8640. °¿346.4 °¿544.1 °¿lineto
  8641. °¿345.5 °¿544.1 °¿lineto
  8642. °¿
  8643. closepath
  8644. °¿gsave
  8645. °¿[0 0 0 1]setcolor  {fill}fp 
  8646. °¿    grestore
  8647. °¿3°¿ sf
  8648. °¿newpath
  8649. °¿346.6 °¿543.9 °¿moveto
  8650. °¿347.5 °¿543.9 °¿lineto
  8651. °¿347.5 °¿543 °¿lineto
  8652. °¿346.6 °¿543 °¿lineto
  8653. °¿
  8654. closepath
  8655. °¿gsave
  8656. °¿[0 0 0 1]setcolor  {fill}fp 
  8657. °¿    grestore
  8658. °¿3°¿ sf
  8659. °¿newpath
  8660. °¿347.5 °¿545 °¿moveto
  8661. °¿348.4 °¿545 °¿lineto
  8662. °¿348.4 °¿544.1 °¿lineto
  8663. °¿347.5 °¿544.1 °¿lineto
  8664. °¿
  8665. closepath
  8666. °¿gsave
  8667. °¿[0 0 0 1]setcolor  {fill}fp 
  8668. °¿    grestore
  8669. °¿3°¿ sf
  8670. °¿newpath
  8671. °¿348.6 °¿543.9 °¿moveto
  8672. °¿349.5 °¿543.9 °¿lineto
  8673. °¿349.5 °¿543 °¿lineto
  8674. °¿348.6 °¿543 °¿lineto
  8675. °¿
  8676. closepath
  8677. °¿gsave
  8678. °¿[0 0 0 1]setcolor  {fill}fp 
  8679. °¿    grestore
  8680. °¿3°¿ sf
  8681. °¿newpath
  8682. °¿322.5 °¿543.9 °¿moveto
  8683. °¿323.4 °¿543.9 °¿lineto
  8684. °¿323.4 °¿543 °¿lineto
  8685. °¿322.5 °¿543 °¿lineto
  8686. °¿
  8687. closepath
  8688. °¿gsave
  8689. °¿[0 0 0 1]setcolor  {fill}fp 
  8690. °¿    grestore
  8691. °¿vmrs
  8692. °¿3°¿ sf
  8693. °¿newpath
  8694. °¿322.5 °¿562 °¿moveto
  8695. °¿323.4 °¿562 °¿lineto
  8696. °¿323.4 °¿561.1 °¿lineto
  8697. °¿322.5 °¿561.1 °¿lineto
  8698. °¿
  8699. closepath
  8700. °¿gsave
  8701. °¿[0 0 0 1]setcolor  {fill}fp 
  8702. °¿    grestore
  8703. °¿3°¿ sf
  8704. °¿newpath
  8705. °¿323.6 °¿560.9 °¿moveto
  8706. °¿324.5 °¿560.9 °¿lineto
  8707. °¿324.5 °¿560 °¿lineto
  8708. °¿323.6 °¿560 °¿lineto
  8709. °¿
  8710. closepath
  8711. °¿gsave
  8712. °¿[0 0 0 1]setcolor  {fill}fp 
  8713. °¿    grestore
  8714. °¿3°¿ sf
  8715. °¿newpath
  8716. °¿322.5 °¿560 °¿moveto
  8717. °¿323.4 °¿560 °¿lineto
  8718. °¿323.4 °¿559.1 °¿lineto
  8719. °¿322.5 °¿559.1 °¿lineto
  8720. °¿
  8721. closepath
  8722. °¿gsave
  8723. °¿[0 0 0 1]setcolor  {fill}fp 
  8724. °¿    grestore
  8725. °¿3°¿ sf
  8726. °¿newpath
  8727. °¿323.6 °¿558.9 °¿moveto
  8728. °¿324.5 °¿558.9 °¿lineto
  8729. °¿324.5 °¿558 °¿lineto
  8730. °¿323.6 °¿558 °¿lineto
  8731. °¿
  8732. closepath
  8733. °¿gsave
  8734. °¿[0 0 0 1]setcolor  {fill}fp 
  8735. °¿    grestore
  8736. °¿3°¿ sf
  8737. °¿newpath
  8738. °¿322.5 °¿558 °¿moveto
  8739. °¿323.4 °¿558 °¿lineto
  8740. °¿323.4 °¿557.1 °¿lineto
  8741. °¿322.5 °¿557.1 °¿lineto
  8742. °¿
  8743. closepath
  8744. °¿gsave
  8745. °¿[0 0 0 1]setcolor  {fill}fp 
  8746. °¿    grestore
  8747. °¿3°¿ sf
  8748. °¿newpath
  8749. °¿323.6 °¿556.9 °¿moveto
  8750. °¿324.5 °¿556.9 °¿lineto
  8751. °¿324.5 °¿556 °¿lineto
  8752. °¿323.6 °¿556 °¿lineto
  8753. °¿
  8754. closepath
  8755. °¿gsave
  8756. °¿[0 0 0 1]setcolor  {fill}fp 
  8757. °¿    grestore
  8758. °¿3°¿ sf
  8759. °¿newpath
  8760. °¿322.5 °¿556 °¿moveto
  8761. °¿323.4 °¿556 °¿lineto
  8762. °¿323.4 °¿555.1 °¿lineto
  8763. °¿322.5 °¿555.1 °¿lineto
  8764. °¿
  8765. closepath
  8766. °¿gsave
  8767. °¿[0 0 0 1]setcolor  {fill}fp 
  8768. °¿    grestore
  8769. °¿3°¿ sf
  8770. °¿newpath
  8771. °¿323.6 °¿554.9 °¿moveto
  8772. °¿324.5 °¿554.9 °¿lineto
  8773. °¿324.5 °¿554 °¿lineto
  8774. °¿323.6 °¿554 °¿lineto
  8775. °¿
  8776. closepath
  8777. °¿gsave
  8778. °¿[0 0 0 1]setcolor  {fill}fp 
  8779. °¿    grestore
  8780. °¿3°¿ sf
  8781. °¿newpath
  8782. °¿322.5 °¿554 °¿moveto
  8783. °¿323.4 °¿554 °¿lineto
  8784. °¿323.4 °¿553.1 °¿lineto
  8785. °¿322.5 °¿553.1 °¿lineto
  8786. °¿
  8787. closepath
  8788. °¿gsave
  8789. °¿[0 0 0 1]setcolor  {fill}fp 
  8790. °¿    grestore
  8791. °¿3°¿ sf
  8792. °¿newpath
  8793. °¿323.6 °¿552.9 °¿moveto
  8794. °¿324.5 °¿552.9 °¿lineto
  8795. °¿324.5 °¿552 °¿lineto
  8796. °¿323.6 °¿552 °¿lineto
  8797. °¿
  8798. closepath
  8799. °¿gsave
  8800. °¿[0 0 0 1]setcolor  {fill}fp 
  8801. °¿    grestore
  8802. °¿3°¿ sf
  8803. °¿newpath
  8804. °¿322.5 °¿552 °¿moveto
  8805. °¿323.4 °¿552 °¿lineto
  8806. °¿323.4 °¿551.1 °¿lineto
  8807. °¿322.5 °¿551.1 °¿lineto
  8808. °¿
  8809. closepath
  8810. °¿gsave
  8811. °¿[0 0 0 1]setcolor  {fill}fp 
  8812. °¿    grestore
  8813. °¿3°¿ sf
  8814. °¿newpath
  8815. °¿323.6 °¿550.9 °¿moveto
  8816. °¿324.5 °¿550.9 °¿lineto
  8817. °¿324.5 °¿550 °¿lineto
  8818. °¿323.6 °¿550 °¿lineto
  8819. °¿
  8820. closepath
  8821. °¿gsave
  8822. °¿[0 0 0 1]setcolor  {fill}fp 
  8823. °¿    grestore
  8824. °¿3°¿ sf
  8825. °¿newpath
  8826. °¿322.5 °¿550 °¿moveto
  8827. °¿323.4 °¿550 °¿lineto
  8828. °¿323.4 °¿549.1 °¿lineto
  8829. °¿322.5 °¿549.1 °¿lineto
  8830. °¿
  8831. closepath
  8832. °¿gsave
  8833. °¿[0 0 0 1]setcolor  {fill}fp 
  8834. °¿    grestore
  8835. °¿3°¿ sf
  8836. °¿newpath
  8837. °¿323.6 °¿548.9 °¿moveto
  8838. °¿324.5 °¿548.9 °¿lineto
  8839. °¿324.5 °¿548 °¿lineto
  8840. °¿323.6 °¿548 °¿lineto
  8841. °¿
  8842. closepath
  8843. °¿gsave
  8844. °¿[0 0 0 1]setcolor  {fill}fp 
  8845. °¿    grestore
  8846. °¿3°¿ sf
  8847. °¿newpath
  8848. °¿322.5 °¿548 °¿moveto
  8849. °¿323.4 °¿548 °¿lineto
  8850. °¿323.4 °¿547.1 °¿lineto
  8851. °¿322.5 °¿547.1 °¿lineto
  8852. °¿
  8853. closepath
  8854. °¿gsave
  8855. °¿[0 0 0 1]setcolor  {fill}fp 
  8856. °¿    grestore
  8857. °¿3°¿ sf
  8858. °¿newpath
  8859. °¿323.6 °¿546.9 °¿moveto
  8860. °¿324.5 °¿546.9 °¿lineto
  8861. °¿324.5 °¿546 °¿lineto
  8862. °¿323.6 °¿546 °¿lineto
  8863. °¿
  8864. closepath
  8865. °¿gsave
  8866. °¿[0 0 0 1]setcolor  {fill}fp 
  8867. °¿    grestore
  8868. °¿3°¿ sf
  8869. °¿newpath
  8870. °¿322.5 °¿546 °¿moveto
  8871. °¿323.4 °¿546 °¿lineto
  8872. °¿323.4 °¿545.1 °¿lineto
  8873. °¿322.5 °¿545.1 °¿lineto
  8874. °¿
  8875. closepath
  8876. °¿gsave
  8877. °¿[0 0 0 1]setcolor  {fill}fp 
  8878. °¿    grestore
  8879. °¿3°¿ sf
  8880. °¿newpath
  8881. °¿323.6 °¿544.9 °¿moveto
  8882. °¿324.5 °¿544.9 °¿lineto
  8883. °¿324.5 °¿544 °¿lineto
  8884. °¿323.6 °¿544 °¿lineto
  8885. °¿
  8886. closepath
  8887. °¿gsave
  8888. °¿[0 0 0 1]setcolor  {fill}fp 
  8889. °¿    grestore
  8890. °¿0°¿ sf
  8891. °¿newpath
  8892. °¿326.6 °¿559.9 °¿moveto
  8893. °¿330.4 °¿559.9 °¿lineto
  8894. °¿330.4 °¿559 °¿lineto
  8895. °¿326.6 °¿559 °¿lineto
  8896. °¿
  8897. closepath
  8898. °¿gsave
  8899. °¿[0 0 0 1]setcolor  {fill}fp 
  8900. °¿    grestore
  8901. °¿0°¿ sf
  8902. °¿newpath
  8903. °¿331.6 °¿559.9 °¿moveto
  8904. °¿335.4 °¿559.9 °¿lineto
  8905. °¿335.4 °¿559 °¿lineto
  8906. °¿331.6 °¿559 °¿lineto
  8907. °¿
  8908. closepath
  8909. °¿gsave
  8910. °¿[0 0 0 1]setcolor  {fill}fp 
  8911. °¿    grestore
  8912. °¿vmrs
  8913. °¿0°¿ sf
  8914. °¿newpath
  8915. °¿330.6 °¿558 °¿moveto
  8916. °¿334.4 °¿558 °¿lineto
  8917. °¿334.4 °¿557.1 °¿lineto
  8918. °¿330.6 °¿557.1 °¿lineto
  8919. °¿
  8920. closepath
  8921. °¿gsave
  8922. °¿[0 0 0 1]setcolor  {fill}fp 
  8923. °¿    grestore
  8924. °¿0°¿ sf
  8925. °¿newpath
  8926. °¿326.6 °¿556 °¿moveto
  8927. °¿330.4 °¿556 °¿lineto
  8928. °¿330.4 °¿555.1 °¿lineto
  8929. °¿326.6 °¿555.1 °¿lineto
  8930. °¿
  8931. closepath
  8932. °¿gsave
  8933. °¿[0 0 0 1]setcolor  {fill}fp 
  8934. °¿    grestore
  8935. °¿0°¿ sf
  8936. °¿newpath
  8937. °¿326.6 °¿558 °¿moveto
  8938. °¿329.4 °¿558 °¿lineto
  8939. °¿329.4 °¿557.1 °¿lineto
  8940. °¿326.6 °¿557.1 °¿lineto
  8941. °¿
  8942. closepath
  8943. °¿gsave
  8944. °¿[0 0 0 1]setcolor  {fill}fp 
  8945. °¿    grestore
  8946. °¿0°¿ sf
  8947. °¿newpath
  8948. °¿331.6 °¿556 °¿moveto
  8949. °¿334.5 °¿556 °¿lineto
  8950. °¿334.5 °¿555.1 °¿lineto
  8951. °¿331.6 °¿555.1 °¿lineto
  8952. °¿
  8953. closepath
  8954. °¿gsave
  8955. °¿[0 0 0 1]setcolor  {fill}fp 
  8956. °¿    grestore
  8957. °¿0°¿ sf
  8958. °¿newpath
  8959. °¿326.6 °¿554 °¿moveto
  8960. °¿330.4 °¿554 °¿lineto
  8961. °¿330.4 °¿553.1 °¿lineto
  8962. °¿326.6 °¿553.1 °¿lineto
  8963. °¿
  8964. closepath
  8965. °¿gsave
  8966. °¿[0 0 0 1]setcolor  {fill}fp 
  8967. °¿    grestore
  8968. °¿0°¿ sf
  8969. °¿newpath
  8970. °¿327.6 °¿547.9 °¿moveto
  8971. °¿338.4 °¿547.9 °¿lineto
  8972. °¿338.4 °¿547.1 °¿lineto
  8973. °¿327.6 °¿547.1 °¿lineto
  8974. °¿
  8975. closepath
  8976. °¿gsave
  8977. °¿[0 0 0 1]setcolor  {fill}fp 
  8978. °¿    grestore
  8979. °¿3°¿ sf
  8980. °¿newpath
  8981. °¿328.5 °¿549 °¿moveto
  8982. °¿329.4 °¿549 °¿lineto
  8983. °¿329.4 °¿548.1 °¿lineto
  8984. °¿328.5 °¿548.1 °¿lineto
  8985. °¿
  8986. closepath
  8987. °¿gsave
  8988. °¿[0 0 0 1]setcolor  {fill}fp 
  8989. °¿    grestore
  8990. °¿3°¿ sf
  8991. °¿newpath
  8992. °¿329.5 °¿550 °¿moveto
  8993. °¿330.4 °¿550 °¿lineto
  8994. °¿330.4 °¿549.1 °¿lineto
  8995. °¿329.5 °¿549.1 °¿lineto
  8996. °¿
  8997. closepath
  8998. °¿gsave
  8999. °¿[0 0 0 1]setcolor  {fill}fp 
  9000. °¿    grestore
  9001. °¿3°¿ sf
  9002. °¿newpath
  9003. °¿330.5 °¿551 °¿moveto
  9004. °¿331.4 °¿551 °¿lineto
  9005. °¿331.4 °¿550.1 °¿lineto
  9006. °¿330.5 °¿550.1 °¿lineto
  9007. °¿
  9008. closepath
  9009. °¿gsave
  9010. °¿[0 0 0 1]setcolor  {fill}fp 
  9011. °¿    grestore
  9012. °¿3°¿ sf
  9013. °¿newpath
  9014. °¿331.5 °¿552 °¿moveto
  9015. °¿332.4 °¿552 °¿lineto
  9016. °¿332.4 °¿551.1 °¿lineto
  9017. °¿331.5 °¿551.1 °¿lineto
  9018. °¿
  9019. closepath
  9020. °¿gsave
  9021. °¿[0 0 0 1]setcolor  {fill}fp 
  9022. °¿    grestore
  9023. °¿3°¿ sf
  9024. °¿newpath
  9025. °¿332.5 °¿553 °¿moveto
  9026. °¿333.4 °¿553 °¿lineto
  9027. °¿333.4 °¿552.1 °¿lineto
  9028. °¿332.5 °¿552.1 °¿lineto
  9029. °¿
  9030. closepath
  9031. °¿gsave
  9032. °¿[0 0 0 1]setcolor  {fill}fp 
  9033. °¿    grestore
  9034. °¿3°¿ sf
  9035. °¿newpath
  9036. °¿336.6 °¿549 °¿moveto
  9037. °¿337.5 °¿549 °¿lineto
  9038. °¿337.5 °¿548.1 °¿lineto
  9039. °¿336.6 °¿548.1 °¿lineto
  9040. °¿
  9041. closepath
  9042. °¿gsave
  9043. °¿[0 0 0 1]setcolor  {fill}fp 
  9044. °¿    grestore
  9045. °¿3°¿ sf
  9046. °¿newpath
  9047. °¿335.6 °¿550 °¿moveto
  9048. °¿336.5 °¿550 °¿lineto
  9049. °¿336.5 °¿549.1 °¿lineto
  9050. °¿335.6 °¿549.1 °¿lineto
  9051. °¿
  9052. closepath
  9053. °¿gsave
  9054. °¿[0 0 0 1]setcolor  {fill}fp 
  9055. °¿    grestore
  9056. °¿3°¿ sf
  9057. °¿newpath
  9058. °¿334.6 °¿551 °¿moveto
  9059. °¿335.5 °¿551 °¿lineto
  9060. °¿335.5 °¿550.1 °¿lineto
  9061. °¿334.6 °¿550.1 °¿lineto
  9062. °¿
  9063. closepath
  9064. °¿gsave
  9065. °¿[0 0 0 1]setcolor  {fill}fp 
  9066. °¿    grestore
  9067. °¿3°¿ sf
  9068. °¿newpath
  9069. °¿333.6 °¿552 °¿moveto
  9070. °¿334.5 °¿552 °¿lineto
  9071. °¿334.5 °¿551.1 °¿lineto
  9072. °¿333.6 °¿551.1 °¿lineto
  9073. °¿
  9074. closepath
  9075. °¿gsave
  9076. °¿[0 0 0 1]setcolor  {fill}fp 
  9077. °¿    grestore
  9078. °¿3°¿ sf
  9079. °¿newpath
  9080. °¿350.6 °¿564 °¿moveto
  9081. °¿351.5 °¿564 °¿lineto
  9082. °¿351.5 °¿563.1 °¿lineto
  9083. °¿350.6 °¿563.1 °¿lineto
  9084. °¿
  9085. closepath
  9086. °¿gsave
  9087. °¿[0 0 0 1]setcolor  {fill}fp 
  9088. °¿    grestore
  9089. °¿3°¿ sf
  9090. °¿newpath
  9091. °¿349.5 °¿562.9 °¿moveto
  9092. °¿350.4 °¿562.9 °¿lineto
  9093. °¿350.4 °¿562 °¿lineto
  9094. °¿349.5 °¿562 °¿lineto
  9095. °¿
  9096. closepath
  9097. °¿gsave
  9098. °¿[0 0 0 1]setcolor  {fill}fp 
  9099. °¿    grestore
  9100. °¿3°¿ sf
  9101. °¿newpath
  9102. °¿350.6 °¿543.9 °¿moveto
  9103. °¿351.5 °¿543.9 °¿lineto
  9104. °¿351.5 °¿543 °¿lineto
  9105. °¿350.6 °¿543 °¿lineto
  9106. °¿
  9107. closepath
  9108. °¿gsave
  9109. °¿[0 0 0 1]setcolor  {fill}fp 
  9110. °¿    grestore
  9111. °¿3°¿ sf
  9112. °¿newpath
  9113. °¿350.6 °¿562 °¿moveto
  9114. °¿351.5 °¿562 °¿lineto
  9115. °¿351.5 °¿561.1 °¿lineto
  9116. °¿350.6 °¿561.1 °¿lineto
  9117. °¿
  9118. closepath
  9119. °¿gsave
  9120. °¿[0 0 0 1]setcolor  {fill}fp 
  9121. °¿    grestore
  9122. °¿3°¿ sf
  9123. °¿newpath
  9124. °¿349.5 °¿560.9 °¿moveto
  9125. °¿350.4 °¿560.9 °¿lineto
  9126. °¿350.4 °¿560 °¿lineto
  9127. °¿349.5 °¿560 °¿lineto
  9128. °¿
  9129. closepath
  9130. °¿gsave
  9131. °¿[0 0 0 1]setcolor  {fill}fp 
  9132. °¿    grestore
  9133. °¿vmrs
  9134. °¿3°¿ sf
  9135. °¿newpath
  9136. °¿350.6 °¿560 °¿moveto
  9137. °¿351.5 °¿560 °¿lineto
  9138. °¿351.5 °¿559.1 °¿lineto
  9139. °¿350.6 °¿559.1 °¿lineto
  9140. °¿
  9141. closepath
  9142. °¿gsave
  9143. °¿[0 0 0 1]setcolor  {fill}fp 
  9144. °¿    grestore
  9145. °¿3°¿ sf
  9146. °¿newpath
  9147. °¿349.5 °¿558.9 °¿moveto
  9148. °¿350.4 °¿558.9 °¿lineto
  9149. °¿350.4 °¿558 °¿lineto
  9150. °¿349.5 °¿558 °¿lineto
  9151. °¿
  9152. closepath
  9153. °¿gsave
  9154. °¿[0 0 0 1]setcolor  {fill}fp 
  9155. °¿    grestore
  9156. °¿3°¿ sf
  9157. °¿newpath
  9158. °¿350.6 °¿558 °¿moveto
  9159. °¿351.5 °¿558 °¿lineto
  9160. °¿351.5 °¿557.1 °¿lineto
  9161. °¿350.6 °¿557.1 °¿lineto
  9162. °¿
  9163. closepath
  9164. °¿gsave
  9165. °¿[0 0 0 1]setcolor  {fill}fp 
  9166. °¿    grestore
  9167. °¿3°¿ sf
  9168. °¿newpath
  9169. °¿349.5 °¿556.9 °¿moveto
  9170. °¿350.4 °¿556.9 °¿lineto
  9171. °¿350.4 °¿556 °¿lineto
  9172. °¿349.5 °¿556 °¿lineto
  9173. °¿
  9174. closepath
  9175. °¿gsave
  9176. °¿[0 0 0 1]setcolor  {fill}fp 
  9177. °¿    grestore
  9178. °¿3°¿ sf
  9179. °¿newpath
  9180. °¿350.6 °¿556 °¿moveto
  9181. °¿351.5 °¿556 °¿lineto
  9182. °¿351.5 °¿555.1 °¿lineto
  9183. °¿350.6 °¿555.1 °¿lineto
  9184. °¿
  9185. closepath
  9186. °¿gsave
  9187. °¿[0 0 0 1]setcolor  {fill}fp 
  9188. °¿    grestore
  9189. °¿3°¿ sf
  9190. °¿newpath
  9191. °¿349.5 °¿554.9 °¿moveto
  9192. °¿350.4 °¿554.9 °¿lineto
  9193. °¿350.4 °¿554 °¿lineto
  9194. °¿349.5 °¿554 °¿lineto
  9195. °¿
  9196. closepath
  9197. °¿gsave
  9198. °¿[0 0 0 1]setcolor  {fill}fp 
  9199. °¿    grestore
  9200. °¿3°¿ sf
  9201. °¿newpath
  9202. °¿350.6 °¿554 °¿moveto
  9203. °¿351.5 °¿554 °¿lineto
  9204. °¿351.5 °¿553.1 °¿lineto
  9205. °¿350.6 °¿553.1 °¿lineto
  9206. °¿
  9207. closepath
  9208. °¿gsave
  9209. °¿[0 0 0 1]setcolor  {fill}fp 
  9210. °¿    grestore
  9211. °¿3°¿ sf
  9212. °¿newpath
  9213. °¿349.5 °¿552.9 °¿moveto
  9214. °¿350.4 °¿552.9 °¿lineto
  9215. °¿350.4 °¿552 °¿lineto
  9216. °¿349.5 °¿552 °¿lineto
  9217. °¿
  9218. closepath
  9219. °¿gsave
  9220. °¿[0 0 0 1]setcolor  {fill}fp 
  9221. °¿    grestore
  9222. °¿3°¿ sf
  9223. °¿newpath
  9224. °¿350.6 °¿552 °¿moveto
  9225. °¿351.5 °¿552 °¿lineto
  9226. °¿351.5 °¿551.1 °¿lineto
  9227. °¿350.6 °¿551.1 °¿lineto
  9228. °¿
  9229. closepath
  9230. °¿gsave
  9231. °¿[0 0 0 1]setcolor  {fill}fp 
  9232. °¿    grestore
  9233. °¿3°¿ sf
  9234. °¿newpath
  9235. °¿349.5 °¿550.9 °¿moveto
  9236. °¿350.4 °¿550.9 °¿lineto
  9237. °¿350.4 °¿550 °¿lineto
  9238. °¿349.5 °¿550 °¿lineto
  9239. °¿
  9240. closepath
  9241. °¿gsave
  9242. °¿[0 0 0 1]setcolor  {fill}fp 
  9243. °¿    grestore
  9244. °¿3°¿ sf
  9245. °¿newpath
  9246. °¿350.6 °¿550 °¿moveto
  9247. °¿351.5 °¿550 °¿lineto
  9248. °¿351.5 °¿549.1 °¿lineto
  9249. °¿350.6 °¿549.1 °¿lineto
  9250. °¿
  9251. closepath
  9252. °¿gsave
  9253. °¿[0 0 0 1]setcolor  {fill}fp 
  9254. °¿    grestore
  9255. °¿3°¿ sf
  9256. °¿newpath
  9257. °¿349.5 °¿548.9 °¿moveto
  9258. °¿350.4 °¿548.9 °¿lineto
  9259. °¿350.4 °¿548 °¿lineto
  9260. °¿349.5 °¿548 °¿lineto
  9261. °¿
  9262. closepath
  9263. °¿gsave
  9264. °¿[0 0 0 1]setcolor  {fill}fp 
  9265. °¿    grestore
  9266. °¿3°¿ sf
  9267. °¿newpath
  9268. °¿350.6 °¿548 °¿moveto
  9269. °¿351.5 °¿548 °¿lineto
  9270. °¿351.5 °¿547.1 °¿lineto
  9271. °¿350.6 °¿547.1 °¿lineto
  9272. °¿
  9273. closepath
  9274. °¿gsave
  9275. °¿[0 0 0 1]setcolor  {fill}fp 
  9276. °¿    grestore
  9277. °¿3°¿ sf
  9278. °¿newpath
  9279. °¿349.5 °¿546.9 °¿moveto
  9280. °¿350.4 °¿546.9 °¿lineto
  9281. °¿350.4 °¿546 °¿lineto
  9282. °¿349.5 °¿546 °¿lineto
  9283. °¿
  9284. closepath
  9285. °¿gsave
  9286. °¿[0 0 0 1]setcolor  {fill}fp 
  9287. °¿    grestore
  9288. °¿3°¿ sf
  9289. °¿newpath
  9290. °¿350.6 °¿546 °¿moveto
  9291. °¿351.5 °¿546 °¿lineto
  9292. °¿351.5 °¿545.1 °¿lineto
  9293. °¿350.6 °¿545.1 °¿lineto
  9294. °¿
  9295. closepath
  9296. °¿gsave
  9297. °¿[0 0 0 1]setcolor  {fill}fp 
  9298. °¿    grestore
  9299. °¿3°¿ sf
  9300. °¿newpath
  9301. °¿349.5 °¿544.9 °¿moveto
  9302. °¿350.4 °¿544.9 °¿lineto
  9303. °¿350.4 °¿544 °¿lineto
  9304. °¿349.5 °¿544 °¿lineto
  9305. °¿
  9306. closepath
  9307. °¿gsave
  9308. °¿[0 0 0 1]setcolor  {fill}fp 
  9309. °¿    grestore
  9310. °¿vmr
  9311. °¿    grestore
  9312. °¿gsave
  9313. °¿%%ChangeFont: Helvetica
  9314. °¿{
  9315. °¿f1 [8 0 0 8 0 0] makesetfont
  9316. °¿324.5 535.298523 moveto
  9317. °¿0 0 32 0 0 (sample) ts
  9318. °¿} 
  9319. °¿
  9320. [0 0 0 1]
  9321. °¿sts
  9322. °¿    grestore
  9323. °¿vmr
  9324. °¿end % FreeHandDict
  9325. †øWå@ˇ ˇˇˇˇ@
  9326. ˇ·ˇ‚7^
  9327. 4H\, Palatino
  9328. .+ä"CHAPTER €`)\1,     Helvetica
  9329.     (@äThe Edition Manager4⁄ä˙(‡ä%Publishers, Subscribers, and Editions
  9330. 
  9331. ‡(‡1ù)-‡)5
  9332. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿
  9333. gHw4gHw"gH_
  9334. ˇ·ˇ‚7^
  9335.     °dONLNdˇˇ(dä
  9336. Figure 1-2°dONLNd\Ãg“)BA0°dONLNd\“g˘)
  9337.  publisherÖ °dONLNd \¯gk)&, an edition, and a subscriber
  9338. °dONLNd* äE(ä*Note that the publisher and subscriber bor˜@°dONLNdT Eï)ªders illustrated in †°dONLNdh ñÆ)QFigurr¿°dONLNdm Ƭ)e 1-2@°dONLNdr √¸)  may appear °dONLNd~ä#∫( ä slightly difRİdONLNdä∫#Δ)0fer5°dONLNdçΔ#›) ent fr´@°dONLNdì›#
  9339. )
  9340. om the borî@°dONLNdù
  9341. #`)0ders you see on scr>`°dONLNd∞a#u)Teen. £°dONLNdµu#ç)Figuru¿°dONLNd∫ç#°)e 1-6@°dONLNdø¢#◊)  shows a scr`°dONLNdÀ◊#)5
  9342. een-capturV¿°dONLNd’#)/ed °dONLNdÿ#ä/B(,ä)image of the publisher and subscriber borØ@°dONLNd#B/ß)∏ders that appear on scrî°dONLNd#ß/∏)eeen.°dONLNd5äA…(>ä
  9343. Data always fló‡°dONLNd+5…A)?ows in one dir¥¿°dONLNd95A.)?
  9344. ection, fry °dONLNdC5/A“)'%om publisher to edition to subscriber¯Ä°dONLNdh5—A )¢ . Documents °dONLNdtAäM
  9345. (JäWthat contain publishers and subscribers do not have to be open at the same time to sharz °dONLNdÀA
  9346. M(J
  9347. e °dONLNdÕMäY∂(VäBdata. Whenever the user saves a document that contains a publisher-İdONLNdM∂Y(V∂, the edition changes °dONLNd%Yäeô(bäto r|‡°dONLNd)Yôe£)eflS@°dONLNd,Y§e’) ect the curr€‡°dONLNd8Y’e)1 ent data fr0@°dONLNdCYeN).om the publisherΔ°dONLNdSYMeR)J. g†°dONLNdUYRe˛)(All subscribers update their contents frj†°dONLNd}Y˛e)¨om °dONLNdÄeäqæ(nä
  9348. the edition. æ`°dONLNdçeæq )4=Any number of subscribers can subscribe to a single edition. °dONLNdÀwäÉê(ÄäTµ¿°dONLNdÃwèÉü)o cr‡Ä°dONLNd–wüÉí)8eate a publisher within a document, a user selects an arh@°dONLNdwìÉ)Ùea of the document to sharù‡°dONLNd"wÉ)ue °dONLNd$ÉäèÕ(åäand chooses Crπ`°dONLNd2ÉÕè)Ceate Publisher fr€†°dONLNdCÉè¯)H6om the Edit menu (illustrated later in this chapter). °dONLNdyèäõ¢(òäFigurR¿°dONLNd~è¢õ∂)e 1-3@°dONLNdÉè∂õ˝)I shows the dialog box that your application should display when the user °dONLNdÃõäßπ(§ä
  9349. chooses CrL@°dONLNd÷õ∫߯)0eate Publisher@°dONLNd‰õ¯ß˙)>.
  9350.  H€4ÀH€"ÀH_
  9351. ˇ·ˇ‚7^
  9352.     °dONLNdˇˇ(»ä
  9353. Figure 1-3°dONLNdÊ¿ÃÀ.)BThe publisher dialog box
  9354. °dONLNdˇ|äàê(ÖäY@İdONLNd|êà‡)our application pr-¿°dONLNd|‡à)P?ovides a thumbnail sketch of the edition data that the Edition °dONLNdQàäî(ëäManager displays in the prh°dONLNdkàî&)weview ar%‡°dONLNdsà'îØ)& ea of the publisher dialog box. +¿°dONLNdìàØîµ)àYÏ@°dONLNdîà¥îœ)our pr¢†°dONLNdöà–î)
  9355. eview of the °dONLNdßîä†%(ùä$edition in this dialog box should pr`°dONLNdÀî&†)ú6ovide a visual cue about the type of information that °dONLNd†ä¨(©ä"the user has selected to publish. 
  9356. wHÛ4wHÛ
  9357. yàÛ4xáyàò2ççyàåœ˚˜ˇı˜ˇ˜˚˜ˇÄˆ˜ˇÄ¯˚˜ˇ¿ˆ˜ˇ¿¯˚˜ˇ‡ˆ˜ˇ‡¯˚˜ˇˆ˜ˇ¯˚˜ˇ¯ˆ˜ˇ¯¯˚˜ˇ¸ˆ˜ˇ¸¯˚˜ˇ˛ˆ˜ˇ˛¯˚ˆˇˆˆˇ¯˚ˆˇÄ˜ˆˇÄ˘˚ˆˇ¿˜ˆˇ¿˘˚ˆˇ‡˜ˆˇ‡˘˚ˆˇ˜ˆˇ˘˚ˆˇ¯˜ˆˇ¯˘˚ˆˇ¸˜ˆˇ¸˘˚ˆˇ˛˜ˆˇ˛˘˚ıˇ˜ıˇ˘˚ıˇÄ¯ıˇÄ˙˚ıˇ¿¯ıˇ¿˙˚ıˇ¿¯ıˇ‡˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ
  9358. ¿ˇˇ˛†ıˇ˙˚ıˇ¿˛ˇ‡ıˇ˙˚ıˇ¿˛ˇ‡ıˇ˙˚Ùˇ
  9359. ¿ćıˇ˙¸üıˇ
  9360. ¿øÛ¿‡ıˇ˙¸ıˇ
  9361. ¿ø˜‡‡ıˇ˙¸ıˇ
  9362. ¿øÓp‡ıˇ˙8Aıˇ
  9363. ¿øÏ0‡ıˇ˙$ÚˇÉøÏ?‡Úˇ‡Ä@ˇ%=MìÚˇ√øÓ‡ÚˇÄ@ˇ93_>ÇÚˇ„æ„‡Úˇ…„7s0!3[0ûÚˇÛæ√√‡Úˇ©óÕO† ˝M.ÇÚˇ„Ň√‡Òˇ‚)ñ≈L ¸Úˇ√É√‡Úˇ«„=s†¸ÚˇÉá8ˇ‡Úˇ˙¸ıˇ
  9364. ¿éˇ‡ıˇ˙¸ıˇ
  9365. ¿ü˛‡ıˇ˙¸ıˇ
  9366. ¿ü˛‡ıˇ˙¸Ùˇ
  9367. ¿ćıˇ˙˚ıˇ¿˛ˇ‡ıˇ˙˚ıˇ¿˛ˇ‡ıˇ˙˚ıˇ¿˛ˇ†ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ
  9368. ¿Çıˇ˙˚ıˇ
  9369. ¿ıˇ˙˚ıˇ
  9370. ¿:fflÄıˇ˙˚ıˇ
  9371. ¿éˇh¿ıˇ˙˚ıˇ
  9372. ¿∂ç´@ıˇ˙˚ıˇ
  9373. ¿vÌ¿ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙œœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœ%˝˛@p˛     @ÄÄÅ˝Ù%˝ ¿à    8Ä@Ä ˝000Ù$˝˝@àĆÄ˝Ù(˝"–˝ø@#Â(à@†}≥»ú„<<ù=‡x}ûs=gĈ'˝!q$îÄ@"%(àA"í)†îê    EãBê%ÑëÑìíı'˝!$ó¿N "…–àA"í(òó–ƒâBê%dëd˙ı'˝!ƒî@D"à    B"í(ÑîFâbê%ëQÇı(˝"9„˚¿‡¯˛úÉ<y›˘€˘Ω«ù⁄ v„Œ„ªé ˆ¸˝˝Ä ˝˝¯ ˆ¸0˝˛ ˝˝¯ ˆ ¸¿ˆp‚œ˝@  @‡ê@½¿¿!Ç Â˝@@Ç
  9374. 0½„ìÃ(Ü/9Áp«óGº
  9375. QˆxÈ˝î4R(…díHH≤»R
  9376. Qâ) È˝ì_À»$íHíHR    óây/†È˝êîpä»§ìH(“LR    âX» È˝fl;œùg~»ÓÌÁπ„ª:›≠ÁÈ Û˘Ë Û˘0ËͿ˜˝¿–¸fl˝@0˛Äfl˝Ä@˛Äfl˝ èæLΩümÿ Δ‡˝ DQRRH§§@    )‡˝ ƒQ_RH§æ@    (‡˝
  9377. $QP<RH§†@    (Ä·˝
  9378. wûÔ√ªo^‰∑ ·¸˝fi¸˝fi ¸8˝€œ˝
  9379. ¿¿¬·˝ @0ĉ˝ @
  9380. ĉ˝¬{ƒÚΔπ¿
  9381. {œx½c"&Câ$ë $§ê†Â˝/">OI"ë 
  9382. '‡ê†Â˝+"6KI#  ë2$"ò†Â˝≈ÒÀÂáù± ¥1¯á«s‹Gpˆ›ˆ›œœ
  9383. ˝ò˝¿`‹˝à  ê‹˝à a‹˝ãg'=‡¡‹˝â($2BÄ!‹˝â&$ÚBÄ!‹˝â!$≤bÇ`ê‹˝‹˛Y¡Ñ`‹œœœò2ççyàåœ˚˜ˇı˜ˇ˜˚¯Ĉ¯į˚¯¿ˆ¯¿¯˚¯`ˆ¯`¯˚¯0ˆ¯0¯˚¯ˆ¯¯˚¯ ˆ¯ ¯˚¯ˆ¯¯˚¯ˆ¯¯˚¯Ę¯Ģ˚¯¿˜¯¿˘˚¯`˜¯`˘˚¯0˜¯0˘˚¯˜¯˘˚¯ ˜v ¸ ˘˚¯˜)ùx¸˘˚¯˜)∞¸˘˚¯į&ïh¸Ä˙˚
  9384. q¿¯¯¿˙˚
  9385. 5np•π¿%Wˇˇ¿¯¯ˇˇ‡˙!˚
  9386. W’‡flWÄ+˛@¯~ja˚0˙#˚
  9387. )V`•YÄ%t@¯Iûë∫U’Ä˝0˙˚ı@¯~û∑oظ0˙˚ı@¯JnùÛG≠¸0˙˚
  9388.  GÄ~<%$Ã@¯ı0˙˚
  9389. UÃÄ> dzÍX@¯ı0˙˚
  9390. _À9¥XwÊÑ@¯ı0˙˚
  9391. NUT®/-ò@¯ı0˙˚ı@¯ı0˙˚ı@¯ı0˙˚
  9392. NlÄN$%$x@¯ı0˙˚
  9393. ∂≈@=∂\z‹»@¯ı0˙$˚
  9394. ¸)¿:¸|¸∞@¯
  9395. PÄ 0˙$˚
  9396. LÿÄL§'%P@¯
  9397. R·“–™MfiNP0˙˚ı@¯
  9398. wÛ∫πˇÓflÌ0˙˚ı@¯
  9399. R°í∞∫M∫Mp0˙˚
  9400. KeÄk$'4H@¯˚¸0˙˚
  9401. ∂ Ä=÷Zj¥@¯ı0˙ ˚
  9402. }Ø?≠zs^t@¯˝ Ä˚0˙!˚
  9403. ŒU^§-%»@¯UZÍeÄ˚0˙˚ı@¯[WoÓÄ˚0˙˚ı@¯$“⁄e¿˚0˙˚
  9404. nLÄO$-$»@¯@@˘0˙˚
  9405. ›•@>fiZwZX@¯ı0˙˚
  9406. 7©¿9’>{vX@¯ı0˙!˚ŒXÄN‰)-H@ˇˇ˛†ı0˙˚ı@˛ˇ‡ı0˙˚ˆD@@˛ˇ‡˜U@0˙˚¯Ä˜ Ä@ć ˜Ã¿0˙$¸ò˛8ĉ @øÛ¿‡˜$0˙+¸%µZ"⁄¥L®@ø˜‡‡  ÑG∞˙+¸%Ì˙?ªÙU¸@øÓp‡ %’–[VÄ    ï ∞˙.*8AÎt"÷ËLË@øÏ0‡o_P˜~Ä
  9407. øÄ@∞˙2    $@˛˝_ˇˇ˝ÉøÏ?‡ˇˇ˚Gw Z›    ù@∞‡Ä@ˇ+%=MìĘò˛à√øÓ‡ààâà@˝@∞Ä@ˇ,93_>Ç D¿J$%<L˛c愇Ė˜ ∞…„7s03!3[0ûUÕÄ:µZz‰ÿ˛æ√√‡Äp,≤,…DÄßâ¿∞©óÕO†3 ˝M.Ç^Õ@:6ƒ˛"cŇ√‡¢""–uUxV´@\õ ˇ‚)ñ≈L 0¸
  9408. OTÄ Ï'ÂX˛√É√‡Äàu“tOÊ¿‚ò¿∞«„=s†$¸@˜_ˇˇ˝Éá8ˇ‡ˇˇ˚$ó(Y]ĸ´@∞˙¸Ę Ä@顇˜@∞˙$¸NF¿N$%&l@ü˛‡ ˜ ∞˙+¸%∂≠Ä=⁄Z{\ÿ@ü˛‡$≤<IƒÄ§Õ¿∞˙+¸%¯^„@:ƒv"¥@ć{UxªK@kõ ∞˙*˚Í\Ä\¨%}H@˛ˇ‡u◊X鿉V¿∞˙"˚ˆD@@˛ˇ‡.ìhÎïÄØ©A∞˙˚ˆàÄ@˛ˇ† ˜Ã«0˙˚
  9409. NEÄO$'4H@¯˜3 0˙˚
  9410. ÷™Ä=æZj¥@¯ı0˙˚
  9411. fiO?EVs^¥@¯ı0˙!˚Jı˛¨-%H@Çı0˙˚ı
  9412. @ı0˙!˚ı@:fflÄx†¿Ä˛0˙*˚$NGÄo$-<H@éˇh¿,î≠“vT‰ÁIH’∞˙*˚$Ω¨Ä>fiZv‰¥@∂ç´@+˛µø~Ïfi⁄ˇ˝_0˙*˚$Á´9•~{‘\@vÌ¿*îØíVT‘÷MH•0˙˚
  9413. ^U^§)%Ë@¯˛˘0˙˚ı@¯ı0˙˚ı@¯
  9414. ¿ë0 ∞˙$˚
  9415. JDÄk&'$ÿ@¯
  9416. &”V„]5’ñË≤i∞˙$˚
  9417. µ´@>÷lZH@¯
  9418. u™≠“ˆ”ªM›˜æ∞˙$˚
  9419. ˇØ¿==bs~à@¯
  9420. 5íµ”U3µL»Úi∞˙˚
  9421. NTÄ ¨-%à@¯˝˙0˙˚ı@¯˝˙0˙$˚
  9422.  GÄn<-§Ã@¯
  9423. @¿Ä `0˙$˚
  9424. UÃÄ>⁄dwZX@¯
  9425. j‰ÁID®•ómÄ0˙$˚
  9426. ^À>4XzˆÑ@¯
  9427. Zfi⁄ˇÎykÍÄ0˙$˚
  9428. OUî)-ò@¯
  9429. d‘÷MD®•ïÎÄ0˙˚ı@¯¸0˙˚ı@¯˙˝0˙#˚
  9430. NLÄK$%&x@¯˝ÅÇÇFÄ0˙$˚
  9431. ∂•@=æ\{\»@¯
  9432. +,§≠ k¶Ø[V†0˙$˚
  9433. ^È¿:˘|"∞@¯
  9434. v˚˛Ÿæ^⁄WzΩ0˙$˚
  9435. ÍXÄN§%}P@¯
  9436. +*§©Æj߯⁄µ†0˙˚ı@¯˝@˛0˙˚ı@¯˝@¸0˙$˚
  9437. NEÄK$'4H@¯
  9438. BÄ ‰ D0˙$˚
  9439. ÷™Ä=÷Zj¥@¯
  9440. R L›+ÊEmdŒ_p˙$˚
  9441. fiO?…zs^t@¯
  9442. jøÌ[ˆÂÔ}Ô]∑p˙$˚
  9443. Jı^§-%»@¯
  9444. R™L˘&ÊDªdÕV∞˙˚ı@¯˛Ä˚0˙˚ı@¯ı0˙˚
  9445. NDÄO$-6H@¯ı0˙˚
  9446. Ω´@>fiZvÏ¥@¯ı0˙˚
  9447. Á´@9’>{“t@¯ı0˙˚
  9448. ^TÄN‰)-»@¯ı0˙˚ı@¯ı0˙˚ı@¯ı0˙˚ı@¯ı0˙˚ı@¯ı0˙˚ı@¯ı0˙˚ı@¯ı0˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙œœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœ%˝˛@p˛     @ÄÄÅ˝Ù%˝ ¿à    8Ä@Ä ˝000Ù$˝˝@àĆÄ˝Ù(˝"–˝ø@#Â(à@†}≥»ú„<<ù=‡x}ûs=gĈ'˝!q$îÄ@"%(àA"í)†îê    EãBê%ÑëÑìíı'˝!$ó¿N "…–àA"í(òó–ƒâBê%dëd˙ı'˝!ƒî@D"à    B"í(ÑîFâbê%ëQÇı(˝"9„˚¿‡¯˛úÉ<y›˘€˘Ω«ù⁄ v„Œ„ªé ˆ¸˝˝Ä ˝˝¯ ˆ¸0˝˛ ˝˝¯ ˆ ¸¿ˆp‚œ˝@  @‡ê@½¿¿!Ç Â˝@@Ç
  9449. 0½„ìÃ(Ü/9Áp«óGº
  9450. QˆxÈ˝î4R(…díHH≤»R
  9451. Qâ) È˝ì_À»$íHíHR    óây/†È˝êîpä»§ìH(“LR    âX» È˝fl;œùg~»ÓÌÁπ„ª:›≠ÁÈ Û˘Ë Û˘0ËͿ˜˝¿–¸fl˝@0˛Äfl˝Ä@˛Äfl˝ èæLΩümÿ Δ‡˝ DQRRH§§@    )‡˝ ƒQ_RH§æ@    (‡˝
  9452. $QP<RH§†@    (Ä·˝
  9453. wûÔ√ªo^‰∑ ·¸˝fi¸˝fi ¸8˝€œ˝
  9454. ¿¿¬·˝ @0ĉ˝ @
  9455. ĉ˝¬{ƒÚΔπ¿
  9456. {œx½c"&Câ$ë $§ê†Â˝/">OI"ë 
  9457. '‡ê†Â˝+"6KI#  ë2$"ò†Â˝≈ÒÀÂáù± ¥1¯á«s‹Gpˆ›ˆ›œœ
  9458. ˝ò˝¿`‹˝à  ê‹˝à a‹˝ãg'=‡¡‹˝â($2BÄ!‹˝â&$ÚBÄ!‹˝â!$≤bÇ`ê‹˝‹˛Y¡Ñ`‹œœœ
  9459. ڊd4ۊd
  9460. ›ºd4‹ª›ºò,
  9461. Y
  9462. Y›ºË’’’’’ŸˇŸŸŸŸŸŸı@¸˚ˇ˛Ûı@¸@˚Ûı@¸Gp≤@Û!˛Ĉ@¯@Dz˙    ÄÇ$˛+ñú¥˜O‡D≤ZRáÚ¸ ¯é¸‚^Ó‡(˛2÷ñ¥˝@¸@d≤ZS‚¸ ã”"R¥ (˛#÷û¥˝@¸HD≤ZQŬ¸ 㔢Ù†$˛"꥘@D≤ZPÄǸ 㔢ц ˛#òú¯˜G¯¸˙    Ó“‚‚‡ı@¸@˚Ûı@¸@˚ÛÔ˚ˇ˛ÛŸ ı@Ê ı@Êı@@Ò¯Ù@Ò¯Ù@ÒǸÄı@@`˜"˚Äı@A‡Δf0sô¿¯˙Ù@©i@‘ò@˘
  9463. :ÄÙ@…o0÷ô@¯ "Äı@@ih0÷ô@¯"Ñ˛ı@@«f0s⿯IJÙG‡Ú ÄÙ@Ò Äı@@Ò˙ı@@Ò@˝˚`IJ@AêÚ¸Ä"˚`¿˝D c#Δ`˘¸ˇ˛˚`‡˝D C!ѧ@˘¯˚@‡˛@@Ñ C!¯¯¸@`˛@AêÑÑ@!¯¯¸¿¸F`c#ƒ ˘¯¸Ä¸@Ò¯˙˝@@Ò¸ˇ˛˙˝@@Ò˚Ä˙¸@Ò˙˙¸@Ò¿˛¸˚@@Ò@˛¸8˚@@Ò JWìK¸x¸@@Ò NfK˝@˚@Ò H7K˝¿<˚@Ò ŒfâŒ˝„ɇ`˛@@Ò˝˝‡¿`˛@@Ò˙˝‡˛‡˝@Ò˚Ä˝ÄÄ˝@Ò¸ˇ˛˛Ä˝@@Ò¯˛Ä˝@@Ò¯˛Ģ@Ò¯Ù@Ò¯˝˙@@Ò¯˝‡¸@@Ò¸Ä˝¸¸@@Ò˝‡˝ ˇ˚@Ò˝˝ˇ¿¸@Ò ˛˝ˇ˝@@Ò&i˛˝<ˇ˝@@ÒÌi˛˝8ˇ‡¸@ÒÔi˛¸ˇ¿¸@Ò-h˛¸ˇ¿˝@@Ò&~˛¸ˇ¿˝@@Ò˛ˇÄ¸ˇ¿¸@Ò˙˝ˇˇ‡¸@Ò¸Ä˝ˇˇ˝@@Ò¸ˇ˛˝ˇˇ¸˝@@Ò¯˝˛ˇ˝@@Ò¯˝˛ˇ¿˝@Ú˛¯˝?˛ˇ‡˝@Ò¯˝?˛ˇ‡˛@@Ò‚¯˝˛ˇ‡˛@@Ò"¯˛˝ˇ¿˝@Ò "òÃΔf3˛˝ˇ¿˝@Ò¯˛˝ˇ¿˛@@Ú¯˛˝ˇ‡˛@@Òǯ˛˝ˇ˝@ÒB¯˛˝ˇ¯˝@Ò¯˛˝ˇ¯‚˛?˝ˇ¸˛@Ê˛?˝ˇ¸˛@Ó¸ˇ˛˛˝ˇ¸Í¸Ä˝˝ˇÙÍ˙˝Á˛ˇÁ¿@Ó˙˝Á¯Ïp@Ó
  9464. $˝Á¯?‡Î
  9465. !Œ3ê&˝Á¯9¡‡˝Ä˛¶@˘
  9466. !Èb–&˝
  9467. Á¯˝¿‡@IJܯ
  9468. !ic–(˝Á¯¿8@§•°$ñ∞µ¶R“˙
  9469. %ibP(˝Ô¯?Á¯˛ ú•°$ñ∞µ¶R–˙
  9470. 9È3ê$˝ˇ∏„‰˛ ¥•Å$Ü∞Ö¶R–˙˙$˝œ∞ÅçÏ˝
  9471. ú§‡ƒg¿„¢L“˙˚Ä˚  @Ó¸Ä˚ d@Ê˚<¯„˙0»„˙p@@Òˇ˛¯˙0˛@@Ò¯˙0¸@Ò˚ˇÄÙ@Ò˚ˇ‡ı@Gı˚‡ı@D+úp‰Á˜¸ÙD0÷ê¥5§˜˚∞ÙE"÷ꥵ§˜˚0ÙE"÷ꥵ§˜ –Ä 0ı@G#÷p‰ıò˜ “úì80ı@@˛Äı Úññ,0Ù@Ò ¬ñì,0Ù@Ò ¬ñï,0ı@@Ò √úì,0ı@Ó˚0
  9472. ·˚0·¸ı@Ó¸ˇ˛`
  9473. ·˚ˇ‡
  9474. ·˚ˇ¿ŸŸŸŸŸˇˇ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’#¯–˛@1¿?¯0$˝ `CÇÄ˝#¯
  9475. @¿J HX $"˝  ¡0`Ä˝#¯˝    @Ñ`H`BbIJ  AÄ˝%¯ë˚{@Ñ¿èî†B°Ä‚{&∂yúgÑ"xÛ›˛%¯≤I$Ä@Ñ àî†C!A$à©RE4í2Ö å)˛%¯I'¿NÑ à'CÒ¿œ$àØÑRE˙ÚÖ å&˛%¯â$@J`àR $! +$à®REíÇb≤ƒ¿é)˛%¯;«Û¿‡1Ä_˙p" q≈ˆœwáè;ø;á_9‡q—˛˜ ¸@˛˝˘¸˜`¸ ˛˝˘0¸˜ÄÛ˘¿¸’’’¯@  @Ú¬@Äp`Û¯¿¿ñF0@Û¯@@Ç(¿Û¯„ìÃ(Ü/9ÁpÉåûNû)BxAÏ˜¯î4R(…díHÇR¢≈°H)C$bR@˜¯ì_À»$íKÄÇ_"D°H&O%‚_@˜¯êîpä»§ìHÇPcD±H$K%aê@˜¯fl;œùg~»ÓÏ«ofi„ŒÏtˆ≥œ‡˜‚ ˆ‚`ˆ‚Ĉ’’’’¯¿–¸Í¯@0˛Äͯ@˛Äͯ æLΩümÿ Δί ÑQRRH§§@    )ί ÑQ_RH§æ@    (ί
  9476. DQP<RH§†@    (Äϯ
  9477. ÁûÔ√ªo^‰∑ Ï˜˝È˜˝È ˜8˝Ê’’’¯
  9478. Ä¿¬Ï¯@@0ÄÔ¯@@
  9479. ÄÔ¯Ñ{ƒÚΔπ¿
  9480. {œx¯Δ"&Câ$ë $§ê†¯^">OI"ë 
  9481. '‡ê†¯V"6KI#  ë2$"ò†¯ãqÀÂáù± ¥1¯á«s‹GpÒËÒË’’’’’¯Ä@Û¸
  9482. 8 Å ˜¯Ä¿ë@D ˛˜¯Ä@ë@ !    ˛˜¯ûyÄëlÔ‰Áº!∫ù¡Ú!åx'∞á∞į¯à°F@ë%ÜHP!ìâ ä2RàbH…Hį¯à°G‡ë$ƒûHP!lâ äÚà"K…|į¯HÒFë$$ñLPLHâ ä≤0å"JΔ@į¯Áé9·˚ü√À#∏0åI«∞˜Yœxwmo=˜Î˛Ä¸Řβĸǘ Ë¿¸ˆò,
  9483. Y
  9484. Y›ºË’’’’’ŸˇŸŸŸŸŸŸı@¸˚ˇ˛Ûı@¸@˚Ûı@¸Gp≤@Û!˛Ĉ@¯@Dz˙    ÄÇ$˛+ñú¥˜O‡D≤ZRáÚ¸ ¯é¸‚^Ó‡(˛2÷ñ¥˝@¸@d≤ZS‚¸ ã”"R¥ (˛#÷û¥˝@¸HD≤ZQŬ¸ 㔢Ù†$˛"꥘@D≤ZPÄǸ 㔢ц ˛#òú¯˜G¯¸˙    Ó“‚‚‡ı@¸@˚Ûı@¸@˚ÛÔ˚ˇ˛ÛŸ ı@Ê ı@Êı@@Ò¯Ù@Ò¯Ù@ÒǸÄı@@`˜"˚Äı@A‡Δf0sô¿¯˙Ù@©i@‘ò@˘
  9485. :ÄÙ@…o0÷ô@¯ "Äı@@ih0÷ô@¯"Ñ˛ı@@«f0s⿯IJÙG‡Ú ÄÙ@Ò Äı@@Ò˙ı@@Ò@˝˚`IJ@AêÚ¸Ä"˚`¿˝D c#Δ`˘¸ˇ˛˚`‡˝D C!ѧ@˘¯˚@‡˛@@Ñ C!¯¯¸@`˛@AêÑÑ@!¯¯¸¿¸F`c#ƒ ˘¯¸Ä¸@Ò¯˙˝@@Ò¸ˇ˛˙˝@@Ò˚Ä˙¸@Ò˙˙¸@Ò¿˛¸˚@@Ò@˛¸8˚@@Ò JWìK¸x¸@@Ò NfK˝@˚@Ò H7K˝¿<˚@Ò ŒfâŒ˝„ɇ`˛@@Ò˝˝‡¿`˛@@Ò˙˝‡˛‡˝@Ò˚Ä˝ÄÄ˝@Ò¸ˇ˛˛Ä˝@@Ò¯˛Ä˝@@Ò¯˛Ģ@Ò¯Ù@Ò¯˝˙@@Ò¯˝‡¸@@Ò¸Ä˝¸¸@@Ò˝‡˝ ˇ˚@Ò˝˝ˇ¿¸@Ò ˛˝ˇ˝@@Ò&i˛˝<ˇ˝@@ÒÌi˛˝8ˇ‡¸@ÒÔi˛¸ˇ¿¸@Ò-h˛¸ˇ¿˝@@Ò&~˛¸ˇ¿˝@@Ò˛ˇÄ¸ˇ¿¸@Ò˙˝ˇˇ‡¸@Ò¸Ä˝ˇˇ˝@@Ò¸ˇ˛˝ˇˇ¸˝@@Ò¯˝˛ˇ˝@@Ò¯˝˛ˇ¿˝@Ú˛¯˝?˛ˇ‡˝@Ò¯˝?˛ˇ‡˛@@Ò‚¯˝˛ˇ‡˛@@Ò"¯˛˝ˇ¿˝@Ò "òÃΔf3˛˝ˇ¿˝@Ò¯˛˝ˇ¿˛@@Ú¯˛˝ˇ‡˛@@Òǯ˛˝ˇ˝@ÒB¯˛˝ˇ¯˝@Ò¯˛˝ˇ¯‚˛?˝ˇ¸˛@Ê˛?˝ˇ¸˛@Ó¸ˇ˛˛˝ˇ¸Í¸Ä˝˝ˇÙÍ˙˝Á˛ˇÁ¿@Ó˙˝Á¯Ïp@Ó
  9486. $˝Á¯?‡Î
  9487. !Œ3ê&˝Á¯9¡‡˝Ä˛¶@˘
  9488. !Èb–&˝
  9489. Á¯˝¿‡@IJܯ
  9490. !ic–(˝Á¯¿8@§•°$ñ∞µ¶R“˙
  9491. %ibP(˝Ô¯?Á¯˛ ú•°$ñ∞µ¶R–˙
  9492. 9È3ê$˝ˇ∏„‰˛ ¥•Å$Ü∞Ö¶R–˙˙$˝œ∞ÅçÏ˝
  9493. ú§‡ƒg¿„¢L“˙˚Ä˚  @Ó¸Ä˚ d@Ê˚<¯„˙0»„˙p@@Òˇ˛¯˙0˛@@Ò¯˙0¸@Ò˚ˇÄÙ@Ò˚ˇ‡ı@Gı˚‡ı@D+úp‰Á˜¸ÙD0÷ê¥5§˜˚∞ÙE"÷ꥵ§˜˚0ÙE"÷ꥵ§˜ –Ä 0ı@G#÷p‰ıò˜ “úì80ı@@˛Äı Úññ,0Ù@Ò ¬ñì,0Ù@Ò ¬ñï,0ı@@Ò √úì,0ı@Ó˚0
  9494. ·˚0·¸ı@Ó¸ˇ˛`
  9495. ·˚ˇ‡
  9496. ·˚ˇ¿ŸŸŸŸŸˇˇ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’#¯–˛@1¿?¯0$˝ `CÇÄ˝#¯
  9497. @¿J HX $"˝  ¡0`Ä˝#¯˝    @Ñ`H`BbIJ  AÄ˝%¯ë˚{@Ñ¿èî†B°Ä‚{&∂yúgÑ"xÛ›˛%¯≤I$Ä@Ñ àî†C!A$à©RE4í2Ö å)˛%¯I'¿NÑ à'CÒ¿œ$àØÑRE˙ÚÖ å&˛%¯â$@J`àR $! +$à®REíÇb≤ƒ¿é)˛%¯;«Û¿‡1Ä_˙p" q≈ˆœwáè;ø;á_9‡q—˛˜ ¸@˛˝˘¸˜`¸ ˛˝˘0¸˜ÄÛ˘¿¸’’’¯@  @Ú¬@Äp`Û¯¿¿ñF0@Û¯@@Ç(¿Û¯„ìÃ(Ü/9ÁpÉåûNû)BxAÏ˜¯î4R(…díHÇR¢≈°H)C$bR@˜¯ì_À»$íKÄÇ_"D°H&O%‚_@˜¯êîpä»§ìHÇPcD±H$K%aê@˜¯fl;œùg~»ÓÏ«ofi„ŒÏtˆ≥œ‡˜‚ ˆ‚`ˆ‚Ĉ’’’’¯¿–¸Í¯@0˛Äͯ@˛Äͯ æLΩümÿ Δί ÑQRRH§§@    )ί ÑQ_RH§æ@    (ί
  9498. DQP<RH§†@    (Äϯ
  9499. ÁûÔ√ªo^‰∑ Ï˜˝È˜˝È ˜8˝Ê’’’¯
  9500. Ä¿¬Ï¯@@0ÄÔ¯@@
  9501. ÄÔ¯Ñ{ƒÚΔπ¿
  9502. {œx¯Δ"&Câ$ë $§ê†¯^">OI"ë 
  9503. '‡ê†¯V"6KI#  ë2$"ò†¯ãqÀÂáù± ¥1¯á«s‹GpÒËÒË’’’’’¯Ä@Û¸
  9504. 8 Å ˜¯Ä¿ë@D ˛˜¯Ä@ë@ !    ˛˜¯ûyÄëlÔ‰Áº!∫ù¡Ú!åx'∞á∞į¯à°F@ë%ÜHP!ìâ ä2RàbH…Hį¯à°G‡ë$ƒûHP!lâ äÚà"K…|į¯HÒFë$$ñLPLHâ ä≤0å"JΔ@į¯Áé9·˚ü√À#∏0åI«∞˜Yœxwmo=˜Î˛Ä¸Řβĸǘ Ë¿¸ˆˇ8@ˇ ˇˇˇˇ@
  9505. ˇ·ˇ‚7^
  9506. 4*\˜, Palatino
  9507. .+l"CHAPTER €`)\1,     Helvetica
  9508.     (@lThe Edition Manager4⁄*˙¯
  9509. (‡*1 )-c)6
  9510.     )9%Publishers, Subscribers, and Editions
  9511. *Draft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯
  9512. °dONLNd\lhs(elA∫†°dONLNd\sh) pr¿°dONLNd\Äh•)
  9513. eview arø†°dONLNd \•h{)%2ea also appears in the subscriber dialog box (see  †°dONLNd>\|hî)◊Figurfi`°dONLNdC\ìhß)e 1-4{‡°dONLNdH\®h∞)). ¢ °dONLNdK\∞h∂)Yb†°dONLNdL\∂h—)our pr°dONLNdR\“hÓ)eview °dONLNdXhlt$(ql+for an edition in this dialog box should pr¨¿°dONLNdÉh$t√)∏%ovide a visual cue about the type of °dONLNd®tlÄŸ(}lTinformation the edition contains. For example, it should allow users to distinguish °dONLNd¸Älåˇ*  between text information and sprÚ‡°dONLNdġåH)ìeadsheet arrays. °dONLNd.ílûî(õlCThe publisher dialog box uses the extended interface of the standarñ °dONLNdqíîû¢(õîd fi>†°dONLNduí£ûÚ)le dialog box that °dONLNdàûl™Í(ßlaccompanies system softwar∫`°dONLNd¢ûÍ™à)~%e version 7.0. The user navigates thr¿°dONLNd«ûâ™ı)üough the contents of the °dONLNd‡™l∂¸(≥ldisk using the mouse or keyboar§°dONLNdˇ™¸∂)êd.°dONLNdºl»s(≈lA∫†°dONLNdºs»—)P user can modify a publisher within a document just like any other portion of a °dONLNdS»l‘ù(—l
  9514. document. €†°dONLNd]»ù‘’)1FAs a default, each time a user saves a document containing a publisher≠‡°dONLNd£»’‘Ò(—’, your °dONLNd™‘l‡T(›l4application should automatically write the publisherÿ‡°dONLNdfi‘U‡¥)È’s data to the edition. ‚@°dONLNdˆ‘¥‡∫)_Y¢¿°dONLNd˜‘∫‡Ù)
  9515. ou also need °dONLNd‡lÏÅ(Èlto pr°dONLNd    ‡ÅϘ)Tovide the user with the choice of sending new publisher data to an edition manually °dONLNd]Ïl¯”(ıl(that is, only at the userÎ@°dONLNdwÏ‘¯˘)h    ’s specifi›†°dONLNdÅÏ˙¯)&c r퇰dONLNdÑϯ*)     equest). l°dONLNdçÏ*¯0)%Y,İdONLNdéÏ0¯i) ou should prˇ`°dONLNdöÏh¯È)8ovide these options by using °dONLNd∑¯lL(l4the publisher options dialog box described later in B °dONLNdίM‡)· “Using Publisher and Subscriber °dONLNd ló(
  9516. l    Options.”°dONLNdl"’*PFor example, one user may choose to automatically update an edition each time a °dONLNde"l.à* ?document is saved. This update mode is useful for a user who cr%`°dONLNd§"â.ı(+âeates a publisher within °dONLNdΩ.l:Å(7la spr °dONLNd¬.Ç:˜)eadsheet application that rİdONLNd›.˜:    )uecor쇰dONLNd·.    :Û)5ds stock information. Each time the user updates the °dONLNd:lF    (Cl#stock information and saves the sprh °dONLNd9:    F€)ù.eadsheet, a new edition automatically becomes °dONLNdgFlR’(Olavailable to subscribers.°dONLNdÅXldo*8Another user may choose to update an edition only upon r¬°dONLNdπXod„(aoequest. This update mode °dONLNd“dlp˛(ml!might be useful for a user who crë °dONLNdÛd˛pÉ)íeates a publisher within a worÓ`°dONLNddÉpñ)Öd-pr% °dONLNddópÛ)ocessing application °dONLNd*pl|…(ylfor a quarterly sales r6°dONLNdAp | )^eport. The user incrW`°dONLNdUp |†)Vementally updates the sales rn†°dONLNdrp†|Δ)Ä    eport thr=†°dONLNd{p«|Ô)'oughout °dONLNdÉ|làë(Öl    the entirh °dONLNdå|ëà∏)%    e quarterÖ‡°dONLNdï|∏àÚ)'J, but does not want this information to be available to subscribers until °dONLNdflàlîÀ(ëlthe end of the quarterè°dONLNdıàÀîµ)_6. Only at the end of each quarter does the user specifi‘ °dONLNd,àµî–)Ícally rÈ@°dONLNd3à–îÔ)equest °dONLNd:îl†~(ùl?to update the edition and make it available to any subscribers.°dONLNdz¶l≤r*Tµ¿°dONLNd{¶q≤Å)o cr‡Ä°dONLNd¶Å≤ı)Ueate a subscriber within a document, the user places the insertion point and chooses °dONLNd‘≤læü(ªl Subscribe T›¿°dONLNdfl≤ûæ≠)2o frÏ °dONLNd„≤≠æ)om the Edit menu. k`°dONLNdı≤æ)UFigur> °dONLNd˙≤æ.)e 1-4€†°dONLNdˇ≤.æ), shows the dialog box that your application °dONLNd+æl I(«l0should display when the user chooses Subscribe T9°dONLNd[æI S)›o. 
  9517. Ì*˛¯4Ó*˛¯"Ó*_
  9518. ˇ·ˇ‚7^
  9519.     °dONLNdˇˇ(Îl
  9520. Figure 1-4°dONLNd_„ÆÓ)BThe subscriber dialog box
  9521. °dONLNdyîl†´(ùlIThe subscriber dialog box also uses the extended interface of the standar†°dONLNd¬î¨†∫(ù¨d fi≈ °dONLNdΔî∫†ı)le dialog box °dONLNd‘†l¨{(©lintrA °dONLNdÿ†|¨˘)oduced with system softwarP °dONLNdÚ†˘¨W)}e version 7.0. InitiallyÔ†°dONLNd    
  9522. †V¨Ë)]", the dialog box should highlight 
  9523. ˝l|¯4˛l|¯
  9524. §|ı4ˇ£§ò,ÙQÙQ§Úı’’’ŸŸŸˇ˙Ÿ
  9525. Ÿ
  9526. Ÿ
  9527. Ÿ
  9528. Ÿ
  9529. Ÿ
  9530. ı ¸˚ˇ˛Û
  9531. ı ¸@˚Û
  9532. ı ¸CÄp“`Û
  9533. !˛@ˆDx@¬˛˙    @¡
  9534. $˛ΩöL“˜O‰B“iKG˘¸ ¸C>q+7p
  9535. (˛≥ZZ“˝ ¸Hr“iKÒ¸ D©-J
  9536. (˛3⁄^“˝ ¸@ B“iH¡·¸ D©Y    zX
  9537. $˛3X“˜D B“iJ¿¡¸ D©Y    BX
  9538.  ˛1úL¸˜C¸¸˙    s)y    1x
  9539. ı ¸@˚Û
  9540. ı ¸@˚Û
  9541. Ô˙ˇÛ
  9542. Ÿ
  9543. ı Ê
  9544. ı Ê
  9545. ı ?Úˇ¸¯
  9546. Ù?Úˇ¸¯
  9547. Ù>o«ˇˇfl¯ˇ¸a˚Ä
  9548. ı 9üüˇˇ˜ˇ¸ë˙
  9549. ı     ;ˇû{Kz^“fl˙ˇ˝    ˘@
  9550. Ù?ÔÜ„KzX“fl˘ˇù˛à@@
  9551. %¸0¸?ÔñÎKzZ“fl˙ˇ¸ë˛@@
  9552. &¸8˝     9üñÎKzZ“fl˙ˇ¸ë˛êÄ@
  9553. "¸8˝ ?˝ˇ˚˜ˇ¸˛êÄ@
  9554. !¸8¸?˝ˇ˚˜ˇ¸˛@@
  9555. ¸0(¸?Úˇ¸˛à@@
  9556. ¸ Ï˝H˛@
  9557. ¸p ˝ Ò˝0˛@
  9558. ˚†˝ Ò˚Ä
  9559. ˚‡Ï˚ˇ
  9560. ˚‡¸¯¯
  9561. ˚Ä˝ cì9Ǣ¯
  9562. ˝˙ cî∞i‰˘¯
  9563. ˝˘fóòid∞˘¯
  9564. ˝˙î¨id∞˘¯
  9565. !˝¯˚ cì9‰˘˚ˇ
  9566. ˝
  9567. ˚ Ò˙
  9568. ˛pxÏ˘@
  9569. ˛xÏ
  9570. ¿@
  9571. ˛˛Ï
  9572. &2‹Œ@
  9573. '˛∞˝ ê˝ ˙
  9574. )jâ)@
  9575. (˛p‡˝     cì{úÂ`˙
  9576. /3    )@
  9577. '˛¿¸Tî¥fî∂ ˙
  9578. (    )@
  9579. #˛p¯fóòg˙
  9580. Δ2ÃŒ@
  9581. ı     6î f¥ ˙˚@
  9582. !˛˚     êcìcú‰ ˙˘@
  9583. ˛ÄÙ¯˙
  9584. ˛?Í˚ˇ
  9585. ˛‡¸ Ò¯
  9586. ˛¯¸ Ò¯
  9587. ˛ġ¸Î¯
  9588. ˛ġ¸Î¯
  9589. ˛ˇ¸Î¯
  9590. ˝ˇ¯¸ Ò¯
  9591. ˝ˇ¸ Ò¯
  9592. ˝ˇÎ
  9593. fs3ôúÿ
  9594. ˝ˇ¯Î¯
  9595. ˝ˇ¯¸ Ò¯
  9596. ˝ˇˇ˛¸ Ò¯
  9597. ˛˛ˇÄϯ
  9598. ˛˛ˇ‡Ï¯
  9599. ˛˛ˇ˝ Ò¯
  9600. ˛˛ˇ¯˝ Ò¯
  9601. ˛˛ˇ¯Ï¯
  9602. ˛˛ˇ¯Ï˚Ä
  9603. ˛˛ˇ¯Ï˘@
  9604. ˛˛ˇ˝ Ò˘@
  9605. ˛˛ˇ¯˝ Ò˛$@
  9606. ˛˝ˇ¸Ï˛ Á1»@
  9607. ˝ˇ˛Ï˛ Â#H@
  9608. ¸ˇ˝ Ò˛!•#»@
  9609. ¸ˇÄ˛ Ò˛%•+@
  9610. ¸ˇÄÌ˛Â1»@
  9611. ¸ˇÄÌ˘@
  9612. ¸ˇÄ˛ Ò˘@
  9613. ˛?˛ˇ¸Ä˛ Ò˚Ä
  9614. ˛<ˇ˛¸¯Ì˚ˇ
  9615. ˛8˛É˝å̯
  9616. ˛8˛¯>̯
  9617. ˛8˛x8˛ Ò¯
  9618. ˛˛ˇ¯˛ Ò¯
  9619. ˛˛ÄxÌ˚ˇÄ
  9620. ˛˛Ô¯˝Ì˚ˇ‡
  9621. ˛˛ÿxᲠÒ˚p
  9622. ˛    ˆ1˘Ä Ò˚∞
  9623. ¸Ã Ì˚0
  9624. ¸çÄÌ˚p
  9625. ¸ª˛ Ò
  9626.  ∞p
  9627. ˚
  9628. ∏˛ Ò
  9629. ◊ò ∏‡p
  9630. ˚ËÌ
  9631. ˇ ÷ï µ†p
  9632. ˚ ÄÌ
  9633. ÷ôµ‡p
  9634. ˚Î
  9635. ë÷ÖµÄp
  9636. ı Ò
  9637. ë wò»∏‡p
  9638. ı Òù˚p
  9639. ‰    ˚p
  9640. ‰ë˚∞
  9641. ı Òa ˚ˇ0
  9642. ı Ò˚ˇ‡
  9643. ‰˚ˇ¿
  9644. Ÿ
  9645. Ÿ
  9646. Ÿ
  9647. Ÿ
  9648. Ÿ
  9649. Ÿ
  9650. Ÿ
  9651. Ÿˇ˙ŸŸˇ˛ˇ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’$˛˛    ˇÄ ˛
  9652.  ÑĈ$Ñ˛    8         ê@ ˛
  9653. 0``Ĉ$IJ    ò    åX@P˛
  9654.  Ĉ%!˙∑‡®ÚîD POc‰¿Ìûs=<«Ñ"xÛ›˜%!é$íê»îB à dë!ëÑì#"2Ö å)˜%!Ç$í¯    –¸dËB ¯‰ëƒëd#ÚÚÖ å&˜%!ÇíÄ    
  9655. D§!dë$ëQ#d≤ƒ¿é)˜%!«<x ˇNAé8æŸÓÒ√Œ„ªú˜é_9‡q—˜˛B¸˝@˛ˆı˛F¸˝Ä˛ˆ0ı˛8ÛĘ¿ı’’’‡¡Ä˛@¯H Î@¡í¿¿ÄÎ@£@@ÄÎ|ryÄ•≈Á<ÓqÅÛ…”fi(O=ûÔRÜä@•,íC    JAX¥)(dåJHÔRbã‡ôyíB…pK·Hî)…‰ºKËÔRéëYíb)J hñ)âd¨2Ô˚Áy·”¨ÔŸ›Ä8Ì„˚‹y›éúæ÷y¸ÔÈÑÓÈåÓÈpÓ’’’’ :¸Ä„ F˛‚PDz‚Q˜…ÄĘ≥̪x¿‰àä*@Å
  9656. Iîà% ‰
  9657. ¯ä+‡Å
  9658. Ió»%„ä*GäIî%‰éÛ›‡8wm„À‹Éˆ‰‰˛Ç˝˛Ä‚˛Ç˝˛Ä‚ «˝Äfl’’’¯@x Ä¯@ÂD¿à`Ä FÁD@à @ AÁxOxû@cÿ◊8GAOc9ÔËLdD»`$í$" AƒîíËE‰G…·    $R$‚ AD¸ËEdF…`â$b$ FDÑS˯æ9|∞Û∂!vÜ?¯Ó{àÓ˯@Ä·¯ÄÄ·’’’’’ >`˝
  9659. Ä@ ¿˛  0 ÄÇ@Ä`@˝P ÄÑ Ä @˝PÛœ0-ù¸ú˜É!S∏>D1興â(»$†ê…
  9660. Ñ!q$FJQ I)˘(¸$òì…
  9661. Ñ!
  9662. ë$^CÒIy/à(¿$Ñí…ä    ÇA    $VFÑIX»éÒ«<?s¯ydwÄâ8ˆÎ9ÔÌ≠ÁêÚĸÚ@¸0  Ô8¸¿Ôò,ÙQÙQ§Úı’’’ŸŸŸˇ˙Ÿ
  9663. Ÿ
  9664. Ÿ
  9665. Ÿ
  9666. Ÿ
  9667. Ÿ
  9668. ı ¸˚ˇ˛Û
  9669. ı ¸@˚Û
  9670. ı ¸CÄp“`Û
  9671. !˛@ˆDx@¬˛˙    @¡
  9672. $˛ΩöL“˜O‰B“iKG˘¸ ¸C>q+7p
  9673. (˛≥ZZ“˝ ¸Hr“iKÒ¸ D©-J
  9674. (˛3⁄^“˝ ¸@ B“iH¡·¸ D©Y    zX
  9675. $˛3X“˜D B“iJ¿¡¸ D©Y    BX
  9676.  ˛1úL¸˜C¸¸˙    s)y    1x
  9677. ı ¸@˚Û
  9678. ı ¸@˚Û
  9679. Ô˙ˇÛ
  9680. Ÿ
  9681. ı Ê
  9682. ı Ê
  9683. ı ?Úˇ¸¯
  9684. Ù?Úˇ¸¯
  9685. Ù>o«ˇˇfl¯ˇ¸a˚Ä
  9686. ı 9üüˇˇ˜ˇ¸ë˙
  9687. ı     ;ˇû{Kz^“fl˙ˇ˝    ˘@
  9688. Ù?ÔÜ„KzX“fl˘ˇù˛à@@
  9689. %¸0¸?ÔñÎKzZ“fl˙ˇ¸ë˛@@
  9690. &¸8˝     9üñÎKzZ“fl˙ˇ¸ë˛êÄ@
  9691. "¸8˝ ?˝ˇ˚˜ˇ¸˛êÄ@
  9692. !¸8¸?˝ˇ˚˜ˇ¸˛@@
  9693. ¸0(¸?Úˇ¸˛à@@
  9694. ¸ Ï˝H˛@
  9695. ¸p ˝ Ò˝0˛@
  9696. ˚†˝ Ò˚Ä
  9697. ˚‡Ï˚ˇ
  9698. ˚‡¸¯¯
  9699. ˚Ä˝ cì9Ǣ¯
  9700. ˝˙ cî∞i‰˘¯
  9701. ˝˘fóòid∞˘¯
  9702. ˝˙î¨id∞˘¯
  9703. !˝¯˚ cì9‰˘˚ˇ
  9704. ˝
  9705. ˚ Ò˙
  9706. ˛pxÏ˘@
  9707. ˛xÏ
  9708. ¿@
  9709. ˛˛Ï
  9710. &2‹Œ@
  9711. '˛∞˝ ê˝ ˙
  9712. )jâ)@
  9713. (˛p‡˝     cì{úÂ`˙
  9714. /3    )@
  9715. '˛¿¸Tî¥fî∂ ˙
  9716. (    )@
  9717. #˛p¯fóòg˙
  9718. Δ2ÃŒ@
  9719. ı     6î f¥ ˙˚@
  9720. !˛˚     êcìcú‰ ˙˘@
  9721. ˛ÄÙ¯˙
  9722. ˛?Í˚ˇ
  9723. ˛‡¸ Ò¯
  9724. ˛¯¸ Ò¯
  9725. ˛ġ¸Î¯
  9726. ˛ġ¸Î¯
  9727. ˛ˇ¸Î¯
  9728. ˝ˇ¯¸ Ò¯
  9729. ˝ˇ¸ Ò¯
  9730. ˝ˇÎ
  9731. fs3ôúÿ
  9732. ˝ˇ¯Î¯
  9733. ˝ˇ¯¸ Ò¯
  9734. ˝ˇˇ˛¸ Ò¯
  9735. ˛˛ˇÄϯ
  9736. ˛˛ˇ‡Ï¯
  9737. ˛˛ˇ˝ Ò¯
  9738. ˛˛ˇ¯˝ Ò¯
  9739. ˛˛ˇ¯Ï¯
  9740. ˛˛ˇ¯Ï˚Ä
  9741. ˛˛ˇ¯Ï˘@
  9742. ˛˛ˇ˝ Ò˘@
  9743. ˛˛ˇ¯˝ Ò˛$@
  9744. ˛˝ˇ¸Ï˛ Á1»@
  9745. ˝ˇ˛Ï˛ Â#H@
  9746. ¸ˇ˝ Ò˛!•#»@
  9747. ¸ˇÄ˛ Ò˛%•+@
  9748. ¸ˇÄÌ˛Â1»@
  9749. ¸ˇÄÌ˘@
  9750. ¸ˇÄ˛ Ò˘@
  9751. ˛?˛ˇ¸Ä˛ Ò˚Ä
  9752. ˛<ˇ˛¸¯Ì˚ˇ
  9753. ˛8˛É˝å̯
  9754. ˛8˛¯>̯
  9755. ˛8˛x8˛ Ò¯
  9756. ˛˛ˇ¯˛ Ò¯
  9757. ˛˛ÄxÌ˚ˇÄ
  9758. ˛˛Ô¯˝Ì˚ˇ‡
  9759. ˛˛ÿxᲠÒ˚p
  9760. ˛    ˆ1˘Ä Ò˚∞
  9761. ¸Ã Ì˚0
  9762. ¸çÄÌ˚p
  9763. ¸ª˛ Ò
  9764.  ∞p
  9765. ˚
  9766. ∏˛ Ò
  9767. ◊ò ∏‡p
  9768. ˚ËÌ
  9769. ˇ ÷ï µ†p
  9770. ˚ ÄÌ
  9771. ÷ôµ‡p
  9772. ˚Î
  9773. ë÷ÖµÄp
  9774. ı Ò
  9775. ë wò»∏‡p
  9776. ı Òù˚p
  9777. ‰    ˚p
  9778. ‰ë˚∞
  9779. ı Òa ˚ˇ0
  9780. ı Ò˚ˇ‡
  9781. ‰˚ˇ¿
  9782. Ÿ
  9783. Ÿ
  9784. Ÿ
  9785. Ÿ
  9786. Ÿ
  9787. Ÿ
  9788. Ÿ
  9789. Ÿˇ˙ŸŸˇ˛ˇ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’$˛˛    ˇÄ ˛
  9790.  ÑĈ$Ñ˛    8         ê@ ˛
  9791. 0``Ĉ$IJ    ò    åX@P˛
  9792.  Ĉ%!˙∑‡®ÚîD POc‰¿Ìûs=<«Ñ"xÛ›˜%!é$íê»îB à dë!ëÑì#"2Ö å)˜%!Ç$í¯    –¸dËB ¯‰ëƒëd#ÚÚÖ å&˜%!ÇíÄ    
  9793. D§!dë$ëQ#d≤ƒ¿é)˜%!«<x ˇNAé8æŸÓÒ√Œ„ªú˜é_9‡q—˜˛B¸˝@˛ˆı˛F¸˝Ä˛ˆ0ı˛8ÛĘ¿ı’’’‡¡Ä˛@¯H Î@¡í¿¿ÄÎ@£@@ÄÎ|ryÄ•≈Á<ÓqÅÛ…”fi(O=ûÔRÜä@•,íC    JAX¥)(dåJHÔRbã‡ôyíB…pK·Hî)…‰ºKËÔRéëYíb)J hñ)âd¨2Ô˚Áy·”¨ÔŸ›Ä8Ì„˚‹y›éúæ÷y¸ÔÈÑÓÈåÓÈpÓ’’’’ :¸Ä„ F˛‚PDz‚Q˜…ÄĘ≥̪x¿‰àä*@Å
  9794. Iîà% ‰
  9795. ¯ä+‡Å
  9796. Ió»%„ä*GäIî%‰éÛ›‡8wm„À‹Éˆ‰‰˛Ç˝˛Ä‚˛Ç˝˛Ä‚ «˝Äfl’’’¯@x Ä¯@ÂD¿à`Ä FÁD@à @ AÁxOxû@cÿ◊8GAOc9ÔËLdD»`$í$" AƒîíËE‰G…·    $R$‚ AD¸ËEdF…`â$b$ FDÑS˯æ9|∞Û∂!vÜ?¯Ó{àÓ˯@Ä·¯ÄÄ·’’’’’ >`˝
  9797. Ä@ ¿˛  0 ÄÇ@Ä`@˝P ÄÑ Ä @˝PÛœ0-ù¸ú˜É!S∏>D1興â(»$†ê…
  9798. Ñ!q$FJQ I)˘(¸$òì…
  9799. Ñ!
  9800. ë$^CÒIy/à(¿$Ñí…ä    ÇA    $VFÑIX»éÒ«<?s¯ydwÄâ8ˆÎ9ÔÌ≠ÁêÚĸÚ@¸0  Ô8¸¿Ôˇ∂@ˇ ˇˇˇˇ@
  9801. ˇ·ˇ‚7^
  9802. 4H\, Palatino
  9803. .+ä"CHAPTER €`)\1,     Helvetica
  9804.     (@äThe Edition Manager4⁄ä˙(‡ä%Publishers, Subscribers, and Editions
  9805. 
  9806. ‡(‡1ù)-‡)7
  9807. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿
  9808. °dONLNd\äh‰(eäQthe name of the last edition published or subscribed to. This allows a user to cr/‡°dONLNdQ\Âh(eÂeate a °dONLNdXhätj(qä3publisher and immediately subscribe to its edition.°dONLNdåzäÜë*A∫†°dONLNdçzëÜ«)
  9809.  subscriber rİdONLNdöz»Ü)7eceives its data fr°dONLNd≠zÜ )L9om a single edition. By default, your application should °dONLNdÊÜäí(èäRautomatically update a document containing a subscriber whenever a new edition is °dONLNd8íäû∂* available. °dONLNdCí∑ûΩ)-Y√İdONLNdDíºû )ou also need to pr⁄`°dONLNdVí û°)O#ovide the user with the choice of rπ‡°dONLNdyí°û)ñeceiving the latest edition °dONLNdïûä™M(ßä,manually (that is, only when the user specifi)`°dONLNd¬ûN™i)ƒcally r>İdONLNd…ûi™ö)
  9810. equests it). ˇ`°dONLNd÷ûö™†)1Yø‡°dONLNd◊û†™…)    ou can prE@°dONLNd‡û ™˛)* ovide these °dONLNdÏ™ä∂∫(≥äFoptions by using the subscriber options dialog box described later in ˜¿°dONLNd2™∫∂(≥∫“Using Publisher °dONLNdC∂䬢(øäand Subscriber Options.”°dONLNd\»ä‘r*3For example, one user may choose to automatically r#†°dONLNdè»s‘)È#eceive new editions as they become °dONLNd≤‘ä‡Ì(›äQavailable. This update mode is useful for a user who subscribes to information frÁ °dONLNd‘̇ (›Ìom an °dONLNd    ‡äÏ&(Èä&edition that consists of daily sales fi, °dONLNd0‡'Ï6)ùgurá`°dONLNd3‡6Ï )"es. This user automatically acquirq†°dONLNdU‡ Ï)îes each version °dONLNdeÏä¯[(ıä1of the sales information as it becomes available.°dONLNdó˛ä
  9811.  *Another user may choose to rÒ¿°dONLNd≥˛ 
  9812. ú)Ç eceive a new edition only upon rR`°dONLNd”˛ù
  9813. )ëequest. This update mode °dONLNdÏ
  9814. ä¸(äis useful for a user who crܰdONLNd
  9815. ¸)r@eates a subscriber to an edition that consists of graphics data °dONLNdGä"A(ä((such as a company logo). The user may rÕ†°dONLNdoA"X)∑equir‰‡°dONLNdtX"    ))e only periodic versions of the logo and °dONLNdù"ä.∫(+ä not need fr¢Ä°dONLNd®"∫.Ó)0Fequent updates. In this case, your application should only update the °dONLNdÓ.ä:m(7ä2subscriber with a new edition when the user specifi´†°dONLNd!.m:à)„cally r¿¿°dONLNd(.à:¥) equests it.°dONLNd4@äLë(IäA∫†°dONLNd5@ëL) user can select, cut, copy¸‡°dONLNdP@ˇLK)n, or paste an entirå@°dONLNdc@LLÄ)M e subscriber∞`°dONLNdo@ÄLÖ)4. R°dONLNdq@ÖL)Although the contents of the °dONLNdéLäX'(Uä"subscriber as a whole can be modifií°dONLNd±L'XÔ)ù/ed, a user cannot edit portions of a subscriberèİdONLNd‡LÔX)». For °dONLNdÊXädf(aä4example, a user can underline or italicize the entirΔ†°dONLNdXfd    )‹'e subscriber text, but cannot delete a °dONLNdAdäp¬(mä
  9816. sentence or rú`°dONLNdNd¬pb)8'otate a single graphical object. This r[°dONLNdudcpò)°
  9817. estriction pr®°dONLNdÇdòp·)5otects the user frè¿°dONLNdîd·p)I
  9818. om losing °dONLNdûpä|(yäUchanges to a subscriber when a new edition arrives. Remember that, as a default, new °dONLNdÛ|äàf* 1editions should automatically update a subscriber§‡°dONLNd$|fàk)‹. FİdONLNd&|kà)$Any changes that a user made to the °dONLNdJàäî (ëä"subscriber text would have to be rv°dONLNdlà î)ñ7eapplied by the user when the new edition arrives. See °dONLNd£îä†˚(ùä“Modifying a Subscriber”5`°dONLNdªî¸†æ)r/ later in this chapter for further information.°dONLNdζä≤ë(ØäA∫†°dONLNd϶ë≤‚)I single document can contain any number or combination of publishers and °dONLNd5≤äæ¿(ªä
  9819. subscribers. T‡°dONLNdB≤¡æŸ)7Figur'†°dONLNdG≤ŸæÌ)e 1-5≈ °dONLNdL≤Ìæ)= shows an example of a document that contains two publishers °dONLNdâæä («ä"and one subscriber (and their corr,@°dONLNd´æ  )ñ0esponding editions). Remember that data always fl*`°dONLNd‹æ )·ows °dONLNd‡ ä÷¥(”ä
  9820. in one dir`°dONLNdÍ µ÷€)+
  9821. ection, fr◊¿°dONLNdÙ €÷~)&%om publisher to edition to subscriberW °dONLNd     ~÷Δ)£. The “Concert flÏ`°dONLNd    * Δ÷ )Hyer” document °dONLNd    8÷ä‚(flä8contains a publisher that is subscribed to by the “Benefií °dONLNd    q÷‚Ò)ıt concert” document. The °dONLNd    ä‚äÓ∫(Îä
  9822. “Concert flŸÄ°dONLNd    ï‚∫Ó‰)0Cyer” document also subscribes to a portion of the “Pianos & palm trôİdONLNd    ÿ‚ÂÓ˙(ÎÂees” °dONLNd    ›Óä˙2(˜ä%document. In addition, the “Concert fl2@°dONLNd
  9823. Ó3˙)©1yer” document as a whole is subscribed to by the °dONLNd
  9824. 4˙ä∏(ä    “Sample fl‘†°dONLNd
  9825. >˙∏ˇ).yer” document. ˇR†@ˇ ˇˇˇˇ@
  9826. ˇ·ˇ‚7^
  9827. 4*\˜, Palatino
  9828. .+l"CHAPTER €`)\1,     Helvetica
  9829.     (@lThe Edition Manager4⁄*˙¯
  9830. (‡*1 )-c)8
  9831.     )9%Publishers, Subscribers, and Editions
  9832. *Draft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯
  9833. g*w¯4g*w¯"g*_
  9834. ˇ·ˇ‚7^
  9835.     °dONLNdˇˇ(dl
  9836. Figure 1-5°dONLNd\Æg¥)BA0°dONLNd\¥gX)( document and its corresponding editions
  9837. °dONLNd*lr(lY@İdONLNd+rˆ)Vou should distinguish each selected publisher and subscriber within a document with a °dONLNdÅlz(lborB °dONLNdÑ{â)der\¿°dONLNdáâı). Display a publisher bor'`°dONLNd†ˆÅ)m der as 3 pixels wide with 50 per« °dONLNd¿ÅŸ)ãcent gray lines, and °dONLNd’l+’((ldisplay a subscriber bor¿°dONLNdÌ÷+a)j der as 3 pixels wide with 75 per¥Ä°dONLNd
  9838. a+¶)ãcent gray lines. ]`°dONLNd¶+≠)EAò°dONLNd≠+≥) r›°dONLNd!≥+Â) ectangle of °dONLNd-+l7((4l+one white pixel should separate the data fr›@°dONLNdX+(7X)º
  9839. om the borΔ@°dONLNdb+X7ì)0der itself. Bor‚ °dONLNdq+ì7ˆ);ders should be drawn °dONLNdÜ7lCà(@loutsidea¿°dONLNdç7âCµ)F the contents of publishers and subscribers so that data is not obscur”İdONLNd”7µC÷(@µed. See  ‡°dONLNd€7◊CÔ)"Figurfi†°dONLNd‡7ÓCı)e °dONLNd‚ClOy(Ll1-6”‡°dONLNdÂCyOı)
  9840.  for an illustration of the born°dONLNdCˆOh)}ders as they appear on scr& °dONLNdCiOé)s    een. See ›¿°dONLNd'CéOÚ)%“Displaying Publisher °dONLNd=Ol[¿(Xland Subscriber Bor^°dONLNdOO¿[ÿ)Tders”s°dONLNdTOÿ[Œ): later in this chapter for detailed information on how to °dONLNdé[lg≠(dl
  9841. implement bor‰°dONLNdõ[≠gÓ)Aders for specifi# °dONLNd´[Ôg0)Bc applications. °dONLNdºmlyÑ(vlFigurR¿°dONLNd¡mÑyò)e 1-6@°dONLNdΔmòyÿ)E shows a document containing a publisher and a document containing a °dONLNd ylÖô(Çl
  9842. subscriberZİdONLNdyôÖ√)-
  9843. , with borÔ¿°dONLNdy√Ö,)*ders displayed for each.°dONLNd8ãló{(îlBor÷@°dONLNd;ã{óç)>ders for publishers and subscribers should behave like the bor= °dONLNdyãéóÙ(îéders of 'PICT' graphics °dONLNdëól£§(†l within a wor`°dONLNdùó•£∏)9d-prU °dONLNd°ó∏£)ocessing document. ”¿°dONLNd¥ó£)YYî@°dONLNdµó£∑)$our application should display a borF`°dONLNdŸó∏£˜)°
  9844. der whenever °dONLNdÊ£lØ|(¨lthe ›`°dONLNdÍ£|Ø)!user clicks within the content ara@°dONLNd £    Øï)ç!ea of a publisher or a subscriberc °dONLNd,£ïØö)å. 5İdONLNd.£ö؆)Yˆ°dONLNd/£üØÂ)our application °dONLNd?Ølª¬(∏lshould hide the borÕ¿°dONLNdRجª¢)V3der whenever the user clicks outside the content ar3`°dONLNdÖØ£ª√)·ea. See 
  9845. w*Ô¯4w*Ô¯
  9846. xLÔı4wKxLò6…©…©xL?ıÀÀÀÀÀÀÀÀÀÀÀÀÀ
  9847. fi¯ˇ¿˘
  9848. fi¯ˇ‡˘
  9849. fi¯ˇ˘
  9850. fi¯ˇ¯˘
  9851. fi¯ˇ¸˘
  9852. fi¯ˇ˛˘fi˜ˇ˘
  9853. fi˜ˇÄ˙
  9854. fi˜ˇ¿˙
  9855. fi˜ˇ‡˙
  9856. fi˜ˇ˙
  9857. fi˜ˇ˙
  9858. fi˜ˇ˙
  9859. fi˜ˇ˙
  9860. fi˜ˇ˙
  9861. fi˜ˇ˙
  9862. fi˜ˇ˙
  9863. fi˜ˇ˙
  9864. fi˜ˇ˙
  9865. fi˜ˇ˙
  9866. fi˜ˇ˙
  9867. fi˜ˇ˙
  9868. fi˜ˇ˙
  9869. fi˜ˇ˙
  9870. fi˜ˇ˙
  9871. fi˜ˇ˙
  9872. fi˜ˇ˙
  9873. fi˜ˇ˙
  9874. fi˜ˇ˙
  9875. fi˜ˇ˙
  9876. fi˜ˇ˙
  9877. fi˜ˇ˙
  9878. fi˜ˇ˙
  9879. fi˜ˇ˙
  9880. fi˜ˇ˙
  9881. fi˜ˇ˙
  9882. fi˜ˇ˙
  9883. fi˜ˇ˙
  9884. fi˜ˇ˙
  9885. fi˜ˇ˙È˛ˇ˚˜ˇ˙È˛ˇ˚˜ˇ˙È˛ˇ˚˜ˇ˙ÈÄp˚˜ˇ˙ÈøÛ¿p˚˜ˇ
  9886. ˛Í‡ø˜‡p¸ɘˇ˛ÍøÓpp¸√˜ˇó3kôÄ˘Ûˇ¯øÏ0p¸„˜ˇ}ˇ˘Ûˇ¸øÏ?s˚ˇÛ˜ˇîÏJaˇ˙Úˇ˛øÓs˚ˇ˚˜ˇw3Àùˇ˙Úˇ˛æ„sˇ˙˙Úˇ¸æ√√sˇ˙˙Úˇ¯Ň√s˚ˇ˚˜ˇ˙˙ÚˇÉ√s˚ˇÛ˜ˇ˙˙‡Û‡á8ˇp¸„˜ˇ˙˙¿Û¿éˇp¸√˜ˇ˙˙?ÄÚü˛p¸ɘˇ˙˙?ÄÚü˛p˚˜ˇ˙˙?ÄÚÄp˚˜ˇ˙˙?ÄÚ˛ˇ˚˜ˇ˙˙?ÄÚ˛ˇ˚˜ˇ˙˙?ÄÚ˛ˇ˚˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÒÊ˘˜ˇ˙˙?ÄÒ˘˜ˇ˙˙?ÄÒ.`˙˜ˇ˙˙?ÄÒ&˙˜ˇ˙˙?ÄÒ&Ä˙˜ˇ˙˙?ÄÒ&p˙˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˙?ÄÁ˜ˇ˙˝˙ˇ˛Í˜ˇ˙˛Ä˚͘ˇ˙˛˙͘ˇ˙˛˙͘ˇ˙˛ÛˇÄÒ˜ˇ˙˛Ûˇ¿Ò˜ˇ˙˛Ûˇ¿Ò˜ˇ˙˛Ûˇ‡Ò˜ˇ˙˛ÛˇÒ˜ˇ˙˛Ûˇ¯Ò˜ˇ˙˛Ûˇ¸Ò˜ˇ˙˛Ûˇ˛Ò˜ˇ˙˛Ûˇ˛Ò˜ˇ˙˛Úˇfi
  9887. ˛ÚˇÄfl
  9888. ˛Úˇ¿fl
  9889. ˛Úˇ‡fl˛ÚˇÔ‡    ˛¯˛ÚˇÔê˛¯˛Úˇ¯Ôñs;ôúÕ∏¯˛Úˇ¸ÔÔOô&S?¯˛Úˇ˛ÔòL"S¯˛ÒˇÔÁKôùíÔ¯
  9890. ˛ÒˇÄ‡
  9891. ˛ÒˇÄ‡
  9892. ˛Òˇ¿‡
  9893. ˛Òˇ¿‡
  9894. ˛Òˇ¿‡
  9895. ˛Òˇ¿‡
  9896. ˛Òˇ¿‡
  9897. ˛Òˇ¿‡
  9898. ˛Òˇ¿‡
  9899. ˛Òˇ¿‡
  9900. ˛Òˇ¿‡
  9901. ˛Òˇ¿‡˛Òˇ¿Ú¯ˇ˘˛Òˇ¿Ú¯ˇ¯˘˛Òˇ¿Ú¯ˇ¸˘˛ÒˇÿÚ¯ˇ˛˘˛ÒˇÃÚ˜ˇ˘˛ÒˇƒÚ˜ˇÄ˙˛ÒˇƒÚ˜ˇ¿˙˛ÒˇƒÚ˜ˇ¿˙˛ÒˇƒÚ˜ˇ‡˙˛ÒˇƒÚ˜ˇ˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛Òˇƒ˛˛ˇ‡˙˜ˇ¯˙˛Òˇƒ˛˛ˇ‡˙˜ˇ¯˙˛Òˇƒ˛˛ˇ‡˙˜ˇ¯˙˛Òˇƒ˛˛‡˙˜ˇ¯˙˛Òˇ    ƒÁć˚˜ˇ¯P@˛˛Òˇ    ƒ Ô¿‡˚˜ˇ¯    @@˛˛Òˇ    ƒ‹‡‡˚˜ˇ¯    óSs0ˇ ˛Òˇ    ƒ?ˇˇÁÿ`‡?¸ˇ¿˜ˇ¯î◊œ†ˇ ˛Òˇ    ƒˇˇÁÿ~‡¸ˇ¿˜ˇ¯î÷àˇ˛Òˇƒ˛ˇÁÃ˛‡˚ˇ¿˜ˇ¯wSK†ˇ˛Òˇ≈˛ˇÁ|Δ‡˚ˇ¿˜ˇ¯˙˛Òˇƒ˛ˇÁ}á܇¸ˇ¿˜ˇ¯˙˛Òˇ    ƒˇˇÁ¡Ü‡?¸ˇ¿˜ˇ¯˙˛Òˇ    ƒ·Ü‡˚˜ˇ¯˙˛Òˇ    ƒ q˛‡˚˜ˇ¯˙˛Òˇ    ƒ9˛‡˚˜ˇ¯˙˛Òˇƒ˛?¸‡˙˜ˇ¯˙˛Òˇƒ˛?¸‡˙˜ˇ¯˙˛Òˇƒ˛˛‡˙˜ˇ¯˙˛Òˇƒ˛˛ˇ‡˙˜ˇ¯˙˛Òˇƒ˛˛ˇ‡˙˜ˇ¯˙˛Òˇƒ˛˛ˇ‡˙˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛Òˇƒ˝pD˘˜ˇ¯˙˛Òˇƒ˝à@˘˜ˇ¯˙˛Òˇƒ˛Ót¿˙˜ˇ¯˙˛Òˇƒ˛<9M ˙˜ˇ¯˙˛Òˇƒ˝úŸM˘˜ˇ¯˙˛Òˇƒ˝l~L‡˙˜ˇ¯˙˛Òˇƒ¸¯˜ˇ¯˙˛Òˇƒ¸¯˜ˇ¯˙˛Òˇƒ¸¯˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇƒÚ˜ˇ¯˙˛ÒˇÃÚ˜ˇ¯˙˛Òˇ»Ú˜ˇ¯˙˛ÒˇÿÚ˜ˇ¯˙˛Òˇ¿Ú˜ˇ¯˙˛Òˇ¿Ú˜ˇ¯˙˛Òˇ¿Ú˜ˇ¯˙˛Òˇ¿Ú˜ˇ¯˙
  9902. ˛Òˇ¿‡
  9903. ˛Òˇ¿‡
  9904. ˛Òˇ¿‡
  9905. ˛Òˇ¿‡˛Òˇ¿Ú–@˜˛Òˇ¿Ú (@˜˛Òˇ¿Ú    7qòÁZ30˘˛Òˇ¿Ú    — |lë’¯˘˛Òˇ¿Ú     tHñ’Dh˘˛Òˇ¿Ú    …ò4„’;∞˘˛Òˇ¿ÌÄı˛Òˇ¿ÌÄı˛Òˇ¿ÌÄı
  9906. ˛Òˇ¿‡
  9907. ˛Òˇ¿‡
  9908. ˛Òˇ¿‡
  9909. ˛Òˇ¿‡
  9910. ˛Òˇ¿‡
  9911. ˛Òˇ¿‡
  9912. ˛Òˇ¿‡
  9913. ˛Òˇ¿‡
  9914. ˛Òˇ¿‡
  9915. ˛Òˇ¿‡
  9916. ˛Òˇ¿‡˛Òˇ¿Ú¯ˇ˘˛Òˇ¿Ú¯ˇ¯˘˛Òˇ¿Ú¯ˇ¸˘˛Òˇ¿Ú¯ˇ˛˘˛Òˇ¿Ú˜ˇ˘˛Òˇ¿Ú˜ˇÄ˙˛Òˇ¿Ú˜ˇ¿˙˛Òˇ¿Ú˜ˇ‡˙˛Òˇ¿Ú˜ˇ˙˛Òˇ¿Ú˜ˇ¯˙˛Òˇ¿Ú˜ˇ¸˙˛Òˇ¿Ú˜ˇ¸˙˛Òˇ¿Ú˜ˇ¸˙˛Òˇ¿Ú˜ˇ¸˙˛Òˇ¿Ú˜ˇ¸˙˛Òˇ¿Ú˜ˇ¸˙˛Òˇ¿Ú˜ˇ¸˙˛Òˇ¿Ú˜ˇ¸˙˛Òˇ¿Ú˜ˇ¸˙˛Òˇ¿Ú˜ˇ¸˙˛Òˇ¿Ú˜ˇ¸˙˛Òˇ¿Ú˜ˇ¸˙˛Òˇ¿Ú˜ˇ¸˙˛Òˇ¿Ú˜ˇ¸˙˛Òˇ¿Ú˜ˇ¸˙˛?Òˇ¿Ú˜ˇ¸˙˛?Òˇ¿Ú˜ˇ¸˙›˜ˇ¸˙˛@ÚÄÚ˜ˇ¸˙˛`ÚÒ˜ˇ¸˙˛?Úˇ˛Ò˜ˇ¸˙
  9917. Û̘ˇ¸˙
  9918. Û̘ˇ¸˙
  9919. Û̘ˇ¸˙
  9920. Û̘ˇ¸˙
  9921. Û̘ˇ¸˙˜` ̘ˇ¸˙˜ê ̘ˇ¸˙¯qõp̘ˇ¸˙¯ ~ ̘ˇ¸˙˜î " ̘ˇ¸˙˜cIfi0̘ˇ¸˙
  9922. Û̘ˇ¸˙Û˘˛ˇ¿˙˜ˇ¸˙Û˘˛ˇ¿˙˜ˇ¸˙˜Ä˘˛ˇ¿˙˜ˇ¸˙˜Ä˘ ˛¿˙˜ˇ¸˙˜€0˘ˇœ¿˙˜ˇ¸˙˜◊†˘ ˇœ¿˙˜ˇ¸˙˜‘ ¯˙`ˇôÅ¿¸ʡ¸˙!˜£†¸˙p ˇ∞¿¿¸¿˜ˇ¸
  9923. ˛ˆ ˘ˇ¯ˇ∞¡¿¸‡˜ˇ¸˛ˆ@˘ˇ¸ ˇ∞¸√˚ˇ˜ˇ¸ó3kôÄÚ˘ˇ˛¯ç√˚ˇ¯˜ˇ¸}ˇÚ¯ˇ ˚ √˚ˇ¸˜ˇ¸îÏJaˇÚ˘ˇÉ
  9924. √˚ˇ¸˜ˇ¸w3ÀùˇÚ˙ˇ˛ √ √˚ˇ¯˜ˇ¸˙Ú˙ˇ¸„
  9925. √˚ˇ˜ˇ¸˙Íx 8s¸¿¸‡˜ˇ¸˙Íp¯¿¸¿˜ˇ¸˙Í@ ¯¿¸ʡ¸˙È¿˙˜ˇ¸˙È
  9926. ˇˇ˛¿˙˜ˇ¸˙È˛ˇÄ˙˜ˇ¸˙È˛ˇ¿˙˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙
  9927. Ë¿¯˜ˇ¸˙
  9928. Ë@¯˜ˇ¸˙Ëmò˘˜ˇ¸˙ËΖ˘˜ˇ¸˙Ëj˘˜ˇ¸˙ËQ–˘˜ˇ¸˙ Á¯˜ˇ¸˙ Á ¯˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙›˜ˇ¸˙
  9929. ›¯ˇ¸˙ÀÀÀÀÀ
  9930. €Äˆ
  9931. €Ä0ˆ €véòu∂˜ €Iº5|˜ €mI†5D˜ €=Nú2<˜ŸˆŸˆŸÙÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ"¸˛    @8˛ 9@˙@˙$ @ı$¸ ¿@    DÄ@ ˝0˙`Ù#¸˝    @`ÑĆ˝˙ Ù,¸&–˝ø@#Â(Ñ@†<Û{Áx\·áøÿÔûÒ··è'Ox‡˜+¸%q$îÄ@"%(àAE â$§í%…HQ%aJ,íBQb–•ˆ,¸&$ó¿N"…–êAE     $æí%H¬Q>ƒaJ$íCÒ"P§¿˜,¸&ƒî@ê"à    "BGåI$†í %H",Q $qJ4ëÇ¢X§ ˜,¸&9„˚¿‡`˛ú|É<sáˆflŸˆ¡√ªü«éÌÔ€¡ÔqÁwƒ˜˚˝˝ÄÚ˛ Ú˚0˝˛Ò˛`Ú˚¿Ë˛ÄÚÀ!¸@  @¿¬@ÄLJ¿Ï!¸¿¿@Fa `ÄÏ!¸@@@†QÄÏ%¸„ìÃ(Ü/9Áp aÔû\ûæ<∫=‡Ràá≥¿$¸î4R(…díHíí¢¢…°H¢EñBêRåH…IÔ$¸ì_À»$íH_Ç¢"H°I DíBêLºK…}Ô$¸êîpä»§ìHPã£cH±I!FíbêH¨JΔAÔ%¸fl;œùg~»ÓÌèpÓfifiÂŒÌ=œÿÈ÷Ìo?ÄÚ¯˘ÄÔÚ¯˘ÄÔflÓÀ¸¿–¸‹¸@0˛Ä‹¸Ä@˛Ä‹¸ èæLΩümÿ Δ›¸ DQRRH§§@    )›¸ ƒQ_RH§æ@    (›¸
  9932. $QP<RH§†@    (Äfi¸
  9933. wûÔ√ªo^‰∑ fi˚˝€˚˝€ ˚8˝ÿÀ¸
  9934. ¿¿¬fi¸ @0Ä·¸ @
  9935. Ä·¸¬{ƒÚΔπ¿
  9936. {œx‚¸c"&Câ$ë $§ê†‚¸/">OI"ë 
  9937. '‡ê†‚¸+"6KI#  ë2$"ò†‚¸≈ÒÀÂáù± ¥1¯á«s‹Gp‚ı⁄ı⁄ÀÀ
  9938. ¸ò˝¿`Ÿ¸à  êŸ¸à aŸ¸ãg'=‡¡Ÿ¸â($2BÄ!Ÿ¸â&$ÚBÄ!Ÿ¸â!$≤bÇ`ꟸ‹˛Y¡Ñ`ŸÀÀÀò6…©…©xL?ıÀÀÀÀÀÀÀÀÀÀÀÀÀ
  9939. fi¯ˇ¿˘fi¸32˛`˘fi˝UT˛p˘fi¸32˛X˘fi˝ ˛L˘fiD@˛F˘fiàÄ ˛C˘fi2" ˛AÄ˙fi˛˛@¿˙fi2" ˛@`˙fiàÄ ˛˙fiD@˝0˙fiàÄ ˝0˙fi2" ˝0˙fi—‡˝0˙fi2b‡˝0˙fi…Ä ˝0˙fif¿˝0˙fi    ÏÄ ˝0˙fi3g ˝0˙fi9˛˝0˙fi33  ˝0˙fi
  9940. πÉå! ˝0˙fi#òBÑ˝0˙fi 'Ö0Å ˝0˙fi0˝˝0˙fi˝˝0˙fi0˝˝0˙fi˛ ˝0˙fi˛˝0˙fi˛å˝0˙fi0˛˝0˙fi˝˝0˙fi0˝˝0˙fi˝ ˝0˙fi˝˝0˙fi˝ ˝0˙fi0˝˝0˙fi˝˝0˙fi0˝˝0˙È˛ˇ˚˛( ˝0˙È˛ˇ˚˛-Ñ˝0˙È˛ˇ˚˛ ˝0˙ÈÄp˚0˛U˝0˙ÈøÛ¿p˚˝˝0
  9941. ˛Í‡ø˜‡p¸Ç0˝˝0˛Í∞øÓpp¸¬˝ ˝0ó3kôÄ"˘ÛˇòøÏ0p¸b˝˝0}ˇ!˘xÛàåøÏ?s˚ˇ≤˝ ˝0îÏJaˇ"˙¿ÛøÓr˚0˝˝0w3Àùˇ˙Úæ„r˚˝˝0˙˙Ú",æ√√r˚".0˛˝0˙˙ ÚŇ√r˚Yå˝0˙˙?Ûˇ∞É√s˚ˇ2≥˝0˙˙‡Û‡á8ˇp¸‚‚å˝0˙˙¿Û¿éˇp¸¬0˝0˙˙0ÄÚü˛p¸Ç ˝0˙˙"ÄÚü˛p˚¸32˝0˙˙ ÄÚÄp˚ ¸Ã˝0˙˙ ÄÚ˛ˇ˚˝UT˝0˙˙(ÄÚ˛ˇ˚ H¿0˙˙ ÄÚ˛ˇ˚ àñQLƒ‰Ú0˙˙ ÄÁ ›˛˙ÀflÀ[◊0˙˙"ÄÁ åñQL’ƒ‘“0˙˙ ÄÁ˜0˙˙ ÄÒÊ˘˜0˙˙(ÄÒ˘˜0˙˙ ÄÒ.`˙ E‡D0˙˙ ÄÒ&˙ .lÕ≠íjΩ0˙˙"ÄÒ&Ä˙ ˝´’mzjWÄ0˙˙ ÄÒ&p˙ -jÕïQ‰µ0˙˙ ÄÁ¿ ˛0˙˙(ÄÁ˜0˙˙ ÄÁ Ä    @ 0˙˙ ÄÁ +ùV-nIh0˙˙"ÄÁ €om]øº0˙˙ ÄÁ '_U-jIh0˙˙ ÄÁ¸@˝0˙˙(ÄÁ¸@˝0˙˙ ÄÁ 9ÄAAÄLÄÄ0˙˙ ÄÁ ˘°ŸSQ»ÌÎê0˙˙"ÄÁ πr∑˝iΩ^fi∏0˙˙ ÄÁ π°’”Q®› ê0˙˙ ÄÁ˜0˙˙(ÄÁ˜0˙˙ ÄÁ˛,Ä0˙˙?ÄÁ slÆñnE“µ`0˙˝˙ˇ˛Í “ØÌ}≠Î’Ô¿0˙˛Ä˚Í “ºù]mE¢≠@0˙˛˙Í˙@0˙˛˙͘0˙˛ÛˇÄÒ˜0˙˛@˛ˇ¿˜¿Ò˚0˙˛@"" ˆ¿ÒtMŒ˚0˙˛@ààĈ‡Òfiµ∂˚0˙˛@DD@ˆ∞Ò‘KÆÄ¸0˙˛@ààĈòÒ˜0˙˛@"" ˆåÒ˜0˙˛@ˆÜÒ˜ˇ˙˛@"" ˆÇÒ˜ˇ˙
  9942. ˛@ààĈÉfi˛@DD@ˆÅÄfl˛@ààĈÄ¿fl˛@"" ˆÄ`fl˛@ˆÄ0Ô‡    ˛¯˛@"" ˆÄÔê˛¯˛@ààĈÄÔñs;ôúÕ∏¯˛@DD@ˆÄ ÔÔOô&S?¯˛@èàῘÄÔòL"S¯˛@#¢/ˆÄÔÁKôùíÔ¯˛@ëˆˇˇÄ‡˛@#‚>ıć˛@è»æı¿‡˛@Eƒnı¿‡˛@ç»Ãı¿‡˛@/‚¸ı¿‡˛@—úı¿‡˛@+„<ı¿‡˛@àÀòı¿‡˛@\Δxı¿‡˛@òÃ∏ı¿‡˛@2Ó8˛˘¿‡˛@˘pı¿Ú¯ˇ˘˛@2˙pı¿ÚĢ8˘˛@®¯Ä8˛˛¿ÚĢ,˘˛ @ ‡pÄH IJÿÚĢ&˘˛@`‡‡ ˛˛ÃÚ˙à#˘ ˛ @`¿    @ê    Ä˛ƒÚĢ!Ä˙"˛A¯É¸ć˛˛ƒÚÅ˚ ¿˙˛@˜ ˛ƒÚǸ @˙˛@˜˛ƒÚĢ `˙˛@˜ 4˛ƒÚѸ 0˙˛@˜|˛ƒÚà¸?¯˙˛@˜x˛ƒÚÄ˚˙˛@˜˝ƒÚIJ˙˛@¯<˝ƒÚDz˙˛@¯¸ƒÚÄ˚˙˛@¯8¸ƒÚÑ˛˙˛@˙`‡¸ƒÚàp˚˙˛@˘√¸ƒÚÄ˚˙˛@¯¸ƒÚÄ˛˙˛@˙~¸ƒÚÇ8˛˛˙˛@˙ ˛ƒÚÄ8˙˙ ˛@˙î0˛ƒÚÑ˝˛˙˛@˚6x˛ƒÚà˚ ˙˛@˚‰¿˛ƒÚÄ‚˚oÄ˙˛@˜¿˛ƒÚÄC˝˝Ä˙˛@ÚƒÚÇ˝Ì¿˙˛@ÚƒÚÄ`˛
  9943. ¶x˙˛@ÚƒÚ
  9944. Ñ`Ã˙˛@ÚƒÚà‡˛Ä>˙˛@ÙăÚÄIJ>>˙˛@Ù¿ƒÚIJ? ˙˛@¯Ä`ƒÚǸ‡~˙˛@¯ÄpƒÚÄ˚Úf˙˛@¯ÄxƒÚѸ˜¬˙˛@¯Ä,ƒÚà˚ ˛¿˙˛@¯¿$ƒÚÄ˙z˙˛@¯5ƒÚÄIJ~˙˛@¯òƒÚ
  9945. ÇÄ4˙˛@ıÃăÚÄIJ$˙˛@ˆFăÚ
  9946. Ñ$˙!˛@˚˝1¬ÄƒÚà ˛d˙"˛@˚˛¯√ăÚÄ    ˛F˙"˛@˚˛aăÚ
  9947. Ä
  9948. ¬˙"˛@˚
  9949. :¬ !ƒÚ
  9950. Ç@Ç˙"˛@˚
  9951. M˛±¸ƒÚ
  9952. Ä≈¿É˙"˛@˚
  9953. N8¿£ƒÚ
  9954. Ñ˛G‡˙"˛@˚
  9955. $ê<pÊŃÚ
  9956. àŒg‡Ä˙!˛@˚
  9957. $é<‹¿¡ƒÚÄÊ$@˝˙˛@ˆÊ@>ƒÚÄ4@˛˙˛@ı√ƒÚÇ??~˛˙˛@˜ˇ·ÄŃÚÄ<p√˝˙˛@¯0Ä¡ƒÚÑ#ôƒ˛˙˛@¯8 ¿aƒÚ
  9958. à>»0˙'˛@¯8¡¿@?!ƒ˛˛ˇ‡˙
  9959. Ä`ˇÄ˙'˛@¯ üxA·±ƒ˛˛ˇ‡˙
  9960. IJ0Ŏ‡˙'˛@¯ 0 A—ƒ˛˛ˇ‡˙
  9961. Ǭµ‡˙'˛@¯‡` qƒ˛˛‡˙
  9962. Ä`√˙,˛@¯‡¿ƒÁć˚Ñ>§P@˛+˛@˜Ń Ô¿‡˚àp ¡à@¿    @@˛-˛@¯L¡ƒ‹‡‡˚Ä Åfip«‡    óSs0ˇ.˛@¯¸hAƒ7ˇˇÁÿ`‡3¸ˇ¿Ä`Éë∑pî◊œ†ˇ.˛@¯¸Ã-·ƒb""'ÿ~‡b¸"@Ç!ÄĬˇî÷àˇ.˛@¯ˇÑ6aƒ¿'Ã˛‡¿¸@Ä;‚Ä@_wSK†ˇ)˛@¯ˇ‰:≈Ä'|Δ‡¿¸ @Ñ#˛Äü‰˙+˛@˙ ˇÊnƒ»ààß}á܇h¸à ¿à¸¿fi` ˙+˛@˙ˇ‚ΔƒwˇˇÁ¡Ü‡3¸ˇ ¿Ä˛A÷    ˙*˛@˙ˇ¬Äƒ·Ü‡˚
  9963. IJAr    Ä˙,˛@¸7KˇÇƒ q˛‡˚
  9964. ǸA`Ä˙,˛@¸    IäˇÇƒ9˛‡˚ĸA˛¿˙+˛@¸ â ˇ¬ ƒ˛?¸‡˙
  9965. Ñ?¸A@˙+˛@¸ ûˇˇ¬ƒ˛?¸‡˙àˇ˛A˛@˙)˛@¸ ,jˇˇÚƒ˛˛‡˙ġˇC¸˙+˛@¸ ˛ˇˇ˛ƒ˛˛ˇ‡˙ġˇ‚˛˙+˛@¸ ˛˛ˇƒ˛˛ˇ‡˙ǡˇÛ˛˙)˛@¸p˛˛ˇàƒ˛˛ˇ‡˙ġˇÒ¸˙˛@¯˛ˇåƒÚÑˇˇÒ˛˙˛@¯˛ˇÑƒÚàˇˇÒ¸˙#˛@¯˛ˇÑƒ˝pD˘Ä?ˇˇ·¸˙%˛@¯˛ˇƒ˝à@˘ÄˇˇÒ˛˙'˛@¯˛ˇƒ˛Ót¿˙ɲˇ˘Ä˛˙&˛@˘˝ˇƒƒ˛<9M ˙Şˇ¸Ä˝˙%˛@˘˝ˇÊƒ˝úŸM˘Ö˛ˇ¸Ä˛˙&˛@˘˝ˇ‚ƒ˝l~L‡˙ⲡ¯Ä‡˙#˛@˘˝ˇ‚ƒ¸¯
  9966. ġˇ¯¿Ò¿˙#˛@˘˝ˇ‚ƒ¸¯
  9967. Ä9ˇˇ@ˇ˙#˛@˘˝ˇ„ƒ¸¯
  9968. Ç9p`ˇ˙˛@¯˛ˇ¡ƒÚ
  9969. Ä9p0ˇ¯˙˛@¯9˛ˇÅƒÚ
  9970. Ñ; pˇ˙˛@¯1¸CÅăÚ
  9971. à;pˇ¯˙˛@¯1¸√Ä¿ƒÚ
  9972. Ä?pˇ0˙˛@¯1¸ÉÄ@ƒÚ
  9973. Ä ˇ˙˛@¯3¸ÉăÚǸ˜˙˛@¯3‹ÉÄÃÚÄ˚‚˙˛@¯?¸ÉÄ»ÚÑ˚D¿˙˛@¯?ÿÉÿÚ˙àà˙˛@Ú¿Úį˙˛@Ú¿Úį˙˛@ˆˇ¿¿Ú˜ˇ¯˙˛@ˆˇ¿¿Ú˜ˇ¯˙˛@ˆˇ¿¿‡ ˛@Ú¿‡ ˛@Ú¿‡ ˛@Ú¿‡˛@Ú¿Ú–@˜ ˛@˝ê¢˝¿Ú (@˜#˛@˝˝Ì˝ˇøˆˇ‡˛¿Ú    7qòÁZ30˘$˛@˛˝Ì¯fløÊˇ‡˛¿Ú    — |lë’¯˘!˛@˚ `˛¿Ú     tHñ’Dh˘˛@Ú¿Ú    …ò4„’;∞˘˛@˝fi†Bx˝¿ÌÄı˛@˝[∑ˇÁÔ(˝¿ÌÄı˛@˝”∑ˇÁÔh˝¿ÌÄı˛@˚Ä`˚¿‡ ˛@Ú¿‡˛ @
  9974. Å–EEP˛¿‡˛@ÔflÔfiuÔü‹¿‡˛@ÔflÔfiuÔü‹¿‡ ˛@Ú¿‡ ˛@Ú¿‡˛ @#@Ñπ˛¿‡˛@ˇΩ˜ÔwœflÛóˇ¿¿‡˛@ˇΩ˜ÔwÀfl„øˇ¿¿‡˛@˜ ˝¿‡˛@Ú¿Ú¯ˇ˘˛@˛ !ƒé˝¿ÚĢ˘˛@˛~ıÌæÂÁfl¸˛¿ÚĢ˘˛@˛˛˜Ì>ÔÂfl¸˛¿ÚĢ˘˛@Ú¿ÚĢ˘˛@Ú¿ÚĢÄ˙#˛@˝p¿0 ˝¿ÚÅ ˛¿˙$˛@˝;∑fiˇœ˜Ä˛¿Ú
  9975. ÅÎEIπ@`˙$˛@˝;∑fiˇœ˜Ä˛¿Ú
  9976. Å>Áú˝U‡0˙˛@˜˝¿Ú
  9977. Å*E MY@˙˛@Ú¿ÚÄ˝˛¸˙˛@˚
  9978. †˚¿ÚÄ˝˝ ˙˛@˚‹‡˚¿ÚÄĢ ˙˛@˚›‡˚¿ÚÅ‘¿˙ ˙˛@˙Ä˙¿ÚÅfiÄ˙ ˙˛@Ú¿Úŧ†˙ ˙˛@Ú¿ÚÄ ˘ ˙˛@Ú¿ÚÄ@˘ ˙˛@Ú¿ÚÄ˙U@ ˙˛@Ú¿ÚÄ ˙ÿ ˙˛@Ú¿ÚĢ3  ˙˛@Ú¿ÚÄ˙@ ˙˛@Ú¿ÚÄ0"˚  ˙˛@Ú¿ÚÄàĸ¿ ˙˛Òˇ¿ÚÄD˚@ ˙˛?Òˇ¿ÚÄàĸ¿ ˙˛?Òˇ¿ÚÄ0"˚  ˙
  9979. ›Ä˚@ ˙˛@ÚÄÚÄ0"˚  ˙˛`ÚÒᇏ¿ ˙˛?Úˇ˛ÒÄt¿¸@ ˙ÛêÌÄπĸ¿ ˙ÛÌÄ0rĸ  ˙ÛÌÄSĸ@ ˙Û0ÌÄ0vĸ  ˙ÛÌ
  9980. ÄŸê@¿ ˙˜` Ì
  9981. Ä’
  9982. 1`@ ˙˜ê êÌ
  9983. Ä◊嬠`¿ ˙¯qõpÌÄ0˝¿  ˙¯ ~ ÌÄ˝¿@ ˙˜î " 0ÌÄ0˝LÄ  ˙˜cIfi0ÌIJ¿¿ ˙ÛÌIJ∞@ ˙Ûê˘˛ˇ¿˙IJÄ Ä¿ ˙Û˘˛ˇ¿˙Ä0˛aÄ  ˙!˜Ä˘˛ˇ¿˙
  9984. Ä`c@ ˙˜Ä0˘ ˛¿˙Ä0˙  ˙˜€0˘ˇœ¿˙Ä˙¿ ˙ ˜◊†˘ ˇœ¿˙Ä˝@ ˙#˜‘ ò˙`ˇôÅ¿¸ÄÄ˝¿ ˙'˜£† ˙p ˇ∞¿¿¸¿Ä0˝pF  
  9985. ˛&ˆ ˙ˇÿˇ∞¡¿¸`Ä˝pg@ ˛%ˆ@¢˙", ˇ∞¸√˚ˇ0Ä0¸
  9986. wÄ  ó3kôÄ#ÚÄ˙¯ç¬˚IJ
  9987. Ä˚Ä¿ }ˇ#Ú¿˙ ˚ ¬˚ ć?ÍÄ@ îÏJaˇ#Úx˙àãÉ
  9988. ¬˚àåÄ¿ˇÔ¿ w3ÀùˇÚ˙ √ ¬˚Ä0˝¿˝p  ˙Ú˙ˇÃ„
  9989. √˚ˇ0Ä˝√Ëp@ ˙Íx 8s¸¿¸`Ä0˝Δ   ˙Íp¯¿¸¿Ä˝èı¯¿ ˙Í@ ¯¿¸ÄIJá1l@ ˙È¿˙Ä˝?±p¿ ˙È
  9990. ˇˇ˛¿˙Ä0˝+Ò¯  ˙È˛ˇÄ˙IJ g˘‡@ ˙È˛ˇ¿˙
  9991. Ä0-gÈÄ  ˙›
  9992. Ä6Pο ˙›
  9993. Ä@?˙@ ˙›
  9994. Ä`˛¿ ˙Ë¿¯Ä0˝ˇˇ  ˙Ë@¯Ä˝ˇ˝@ ˙Ëmò˘Ä0˛ˇ˝  ˙ËΖ˘IJˇ˝¿ ˙Ëj˘Ä˛ˇ˝Ä@ ˙ËQ–˘Ä˝¸,¿¿ ˙Á¯Ä0˝¸l  ˙Á ¯Ä˝¸L@ ˙›Ä0˝ˇ¯  ˙›Ä˝ˇ¯¿ ˙ ›Ä˙@ ˙ ›Ä˙¿ ˙›
  9995. Ä0ˇ˛  ˙ ›Ä˙@ ˙›
  9996. Ä0Ôˇ  ˙ ›Ä˙¿ ˙›
  9997. ġΡ@ ˙ ›Ä˙¿ ˙›
  9998. Ä0ˇ˜ˇ¯  ˙ ›Ä˙@ ˙›
  9999. Ä0ˇˇ  ˙ ›Ä˙¿ ˙›
  10000. ġˇ¸@ ˙ ›Ä˙¿ ˙›Ä0¯˛  ˙ ›Ä˙@ ˙ ›Ä˘3  ˙ ›Ä ˙ÿ ˙ ›Ä˙U@ ˙›˜ˇ¸˙
  10001. ›¯ˇ¸˙ÀÀÀÀÀ
  10002. €Äˆ
  10003. €Ä0ˆ €véòu∂˜ €Iº5|˜ €mI†5D˜ €=Nú2<˜ŸˆŸˆŸÙÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ"¸˛    @8˛ 9@˙@˙$ @ı$¸ ¿@    DÄ@ ˝0˙`Ù#¸˝    @`ÑĆ˝˙ Ù,¸&–˝ø@#Â(Ñ@†<Û{Áx\·áøÿÔûÒ··è'Ox‡˜+¸%q$îÄ@"%(àAE â$§í%…HQ%aJ,íBQb–•ˆ,¸&$ó¿N"…–êAE     $æí%H¬Q>ƒaJ$íCÒ"P§¿˜,¸&ƒî@ê"à    "BGåI$†í %H",Q $qJ4ëÇ¢X§ ˜,¸&9„˚¿‡`˛ú|É<sáˆflŸˆ¡√ªü«éÌÔ€¡ÔqÁwƒ˜˚˝˝ÄÚ˛ Ú˚0˝˛Ò˛`Ú˚¿Ë˛ÄÚÀ!¸@  @¿¬@ÄLJ¿Ï!¸¿¿@Fa `ÄÏ!¸@@@†QÄÏ%¸„ìÃ(Ü/9Áp aÔû\ûæ<∫=‡Ràá≥¿$¸î4R(…díHíí¢¢…°H¢EñBêRåH…IÔ$¸ì_À»$íH_Ç¢"H°I DíBêLºK…}Ô$¸êîpä»§ìHPã£cH±I!FíbêH¨JΔAÔ%¸fl;œùg~»ÓÌèpÓfifiÂŒÌ=œÿÈ÷Ìo?ÄÚ¯˘ÄÔÚ¯˘ÄÔflÓÀ¸¿–¸‹¸@0˛Ä‹¸Ä@˛Ä‹¸ èæLΩümÿ Δ›¸ DQRRH§§@    )›¸ ƒQ_RH§æ@    (›¸
  10004. $QP<RH§†@    (Äfi¸
  10005. wûÔ√ªo^‰∑ fi˚˝€˚˝€ ˚8˝ÿÀ¸
  10006. ¿¿¬fi¸ @0Ä·¸ @
  10007. Ä·¸¬{ƒÚΔπ¿
  10008. {œx‚¸c"&Câ$ë $§ê†‚¸/">OI"ë 
  10009. '‡ê†‚¸+"6KI#  ë2$"ò†‚¸≈ÒÀÂáù± ¥1¯á«s‹Gp‚ı⁄ı⁄ÀÀ
  10010. ¸ò˝¿`Ÿ¸à  êŸ¸à aŸ¸ãg'=‡¡Ÿ¸â($2BÄ!Ÿ¸â&$ÚBÄ!Ÿ¸â!$≤bÇ`ꟸ‹˛Y¡Ñ`ŸÀÀÀˇ ¯@ˇ ˇˇˇˇ@
  10011. ˇ·ˇ‚7^
  10012. 4H\, Palatino
  10013. .+ä"CHAPTER €`)\1,     Helvetica
  10014.     (@äThe Edition Manager4⁄ä˙(‡ä%Publishers, Subscribers, and Editions
  10015. 
  10016. ‡(‡1ù)-‡)9
  10017. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿
  10018. °dONLNd\ähB(eä(“Displaying Publisher and Subscriber Bor6‡°dONLNd(\Ch[)πders”K‡°dONLNd-\[hÎ)$ later in this chapter for detailed °dONLNdQhät1(qä#information on how to implement bor<°dONLNdth2ts)®ders for specifi{ °dONLNdÑhst¥)Ac applications. 
  10019. óH®4òH®"òH_
  10020. ˇ·ˇ‚7^
  10021.     °dONLNdˇˇ(ïä
  10022. Figure 1-6°dONLNdïçÃòP)B Publisher and subscriber borders
  10023. °dONLNd∂˜äê(äY@İdONLNd∑˜ê,)#ou also need to support the standarí°dONLNd⁄˜,)ú,d Edition Manager menu commands in the Edit °dONLNdä( ämenu. These menu items include,
  10024.  
  10025. Zapf Dingbats
  10026. °dONLNd%äè*n
  10027. °dONLNd'ñ!°) Cr\°dONLNd)°!È) eate Publisher…
  10028. °dONLNd9*ä1è(0än
  10029. °dONLNd;'ñ3…) Subscribe T›¿°dONLNdF'»3◊)2o…
  10030. °dONLNdI<äCè(Bän
  10031. °dONLNdK9ñE$) Publisher/Subscriber Options…
  10032. °dONLNdiNäUè(Tän
  10033. °dONLNdkKñW›)
  10034. Show/Hide Borb@°dONLNdxK›W)Gders (optional)
  10035. °dONLNdà`ägè(fän
  10036. °dONLNdä]ñi¨) Stop õ`°dONLNdè]¨i)All Editions (optional)°dONLNdßoä{Ω(xäBUse a dotted line to separate the Edition Manager menu commands fr<°dONLNdÈoæ{(xæom the standarî`°dONLNd˜o{)Bd °dONLNd˘{äá(ÑäEdit menu commands Cut, CopyÚ¿°dONLNd{áN)ê
  10037. , and Paste. ≤İdONLNd"{Oág)5FigurÖ@°dONLNd'{gá{)e 1-7"¿°dONLNd,{|áŒ) shows the standar…İdONLNd>{Œá˘)R
  10038. d Edition °dONLNdHáäì(êäManager menu commands.
  10039. ßäfl4®äfl†Çò"8Änê8Ünâ©ãflãflfl‚ˇĄĄĄø˜˝ˇ¯Ú˝ˇ˛ˇÔÿÄ@˚ |`f¿0 ˘Ç !ø@˝ˇ¯f``¿0 ˝ˇ˛Ç/ÿÄ@˚
  10040. ff|f8¯xÿ>6|xÿ˚Ç  ø@˝ˇ¯˝f
  10041. dÃÇ338ÃÇ˝ˇ˛Ç/ÿÄ@˚|˛f    pÃÿ330Ãÿ˚Ç !ø@˝ˇ¯`˛f
  10042. 8ø¿330ø¿˝ˇ˛˛/ÿÄ@˚`˛f    ÿ¿330ÿ¿˚Ä !ø@˝ˇ¯`˛f
  10043. Lÿ330ÿ˝ˇ˛Ä/ÿÄ@˚
  10044. `>|f8Ãx¿>0|x¿˚Ä ø˜˝ˇ¯Ú˝ˇ˛ˇÔÿĄĄĄ‚ˇ¯
  10045. ÄÂ
  10046. ÄÂ
  10047. ÄÂ
  10048. ÄÂ$
  10049. ÄÂB
  10050. ÄÂÅ
  10051. Ä    ò
  10052. ÄÂ √ÿ
  10053. ÄÂB
  10054. ÄÂB
  10055. ÄÂB
  10056. ÄÂ~
  10057. ÄÂÄÔˇ˛˙ÄÔlˇ¯¸ˇ¯ÄÔ˛ˇ˙oˇ‡˛ˇ¯ÄˆÌªn€.†˛ 8ÄˇˇÔ˚˛˚†˛ 8Ä~Ó€ªn…≤`˛ 8ÄÒˇˇ˛Ô˚øn‡˛ 8ÄÒÏÕõª&l…†˛ 8Ä
  10058. ˘™¸ˇˇ˛ÓÌ€ª†˛ 8ĢU¸¿Ã…ôõª2f†˛ 8Ä
  10059. ˘™˝    ‡32fÓœ†˛ 8Ä˙˝ ?¸˝ö†˛ 8"Ä˛˝    ˇˇ¿?†˛ 8!ġú˛˝˝¯k†˛ 8! Ä∞ÁĽĽ¸ˇ†˛ 8! ć?¸˝ˇ‡˝    ø†˛ 8" Ä«˝    ˇˇ¸ ˚‡˛ 8" ̇˝     ˛◊@˛ˇ¯" Ä>~<˝    ‡ˇ˛ø¿˛àò" Ęī˝    ?¯~IJ
  10060. "8" ġ¸?ú˝ ˛ˇà˝Ä˛àò  Ä9?`0ò˝`˝?à+˝
  10061. "8 Äo~¯`Ë˝`¸˛˝àò ÄD˜Éˇ¿8˝ ˚§˝
  10062. "8 Ä¡ˇˇÄ|˝ˇ¸l˝àò! Ä«ˇ¯‹˝[ˇÄ˛»˝
  10063. "8! Ä    å?ˇ¿Ï˝Z≠ˇˇ‡∏˝àò! ă?ˇ¯?É˝Z≠j∂ˇ‡ ˝
  10064. "8! Äÿˇ˛Ê˝≠j∂ªø˛`˝àò! Äpøˇ√Ù˝¯/˙∂˚£™¿˝
  10065. "8  ġˇ<¸ˇ˛øÍˇ™Ä˝àò ġˇ?¸˙¸˛´Ä˝
  10066. "8 ÄflˇÌÿ˘ˇˇ´¸àòIJˇˇÔ‡˜˛¸
  10067. "8IJˇ©‡àòIJˇª‡
  10068. "8IJˇ˜‡àòÄ˝ˇ¿
  10069. "8Ä˝«‡àòĸ 
  10070. "8ĸ@àòĸ`
  10071. "8ĸ†àòĸ‡
  10072. "8Ä˙àòÄ˙
  10073. "8Ä
  10074. ˘™˙ˇ¯àòĢU˚Å˘
  10075. "8Ä
  10076. ˘™˚>fl¯˙àòÄ˘∂¿˚
  10077. "8ÄÛ˜˝æˇ‡¸àòÄÒÜ›∑Ȇ?¸
  10078. "8ÄÒ?∑˝øˇmÄ˝àòÄÒ fÌìm∂ŸÄ˝
  10079. "8ÄÒ9ˇøˇÔ˜Ä˝àòÄÒc&m€m∫DÄ˝
  10080. "8ÄÚœ˝ˇ˚Ô‹Ä˝àòÄÚ$ŸnõpÄ˝
  10081. "8ÄÚ~Óˇ˜˚˛¡Ä˝àòÄÚqŸª∂]¶ŸáÄ˝
  10082. "8ÄÛ    «wÓ˝˜ˇ≥ Ä˝àòÄÛ     Ãô∑m≤ÓÄ˝
  10083. "8ÄÛ    ˇ˜˝ˇÔ∏~Ä˝àòÄÛ    LDÃìd∫ €Ä˝
  10084. "8ÄÛ    flªˇflÓ„˛Ä˝àòÄÛ    Ävn€vŸÇ[Ä˝
  10085. "8ÄÙ
  10086. Ä˚∂›˜˛Ä˝àòÄÙ
  10087. ‡˝∑ÃÄ˝
  10088. "8ÄÙ
  10089. ?¿˝∏ˇÄ˝àòÄÙ    ¿‡€˚¸
  10090. "8ÄÙÄ|˛É∑∂¸àòÄÙ    ˇ¯ܡ¸¸
  10091. "8ÄÙ    Ä
  10092. ∑ê¸àòÄÙ    ˇˇ?ˇp¸
  10093. "8ÄÙ    ˛l∂¿¸àòÄÙ    ?˛˚ˇÄ¸
  10094. "8ÄÙ˛?‡&≤˚àòÄÙ˛ˇ◊ˇÓ˚
  10095. "8ÄÙ˝¸6ò˚àòÄÙ˝¯˚
  10096. "8ÄÙ 8˝6¿˚àòÄÙ8˝ˇÄ˚
  10097. "8ÄÙ8˝∂˙àòÄÙ¸˝Ï˙
  10098. "8ÄÛ¿˛∏˙àòÄÚÄ`˙ˇ¯ÄÒ¿˙ÄÒ‡Ä˙Ä>˘~Ä¸˘BÄÔ¯˘BÄÓp˘B
  10099. ÄÂ √ÿ
  10100. Ä    ò
  10101. ÄÂÅ
  10102. ÄÂB
  10103. ÄÂ$
  10104. ÄÂ
  10105. ÄÂ
  10106. Ä‚ˇ¯ÄˇˇÍ"$ÅÄÍàåÉÄÍ"$    ¸ÖÄÍàå    âÒÄÍ"$|âÿêÄÍàå@IX†ÄÍ"$@)X†ÄÍàå@)XêÄÍ"$@I¸XâÒÄÍàå|à@XÖÄÍ"$@XÉÄÍàå@XÅÄÍ"$ÿġˇÍà傎¯„ˇ¯flflflflflflfl„ˇ¯@„ @„ @„ _ø˚˝ˇ¸Ú¸ˇ˜Ï@ ¸Ä ˛Ã˛¿˙A  _† ˝ˇ¸@ ˛ ˛¿¸ˇAÏ@ ¸ œá6œáçÉ·„g«çĸA  _† ˝ˇ¸ ÃÃô8ÃÃŒ33åÃŒ¸ˇAÏ@ ¸åÃŒ0˛Ã33 ÃÃ˚A  _† ˝ˇ¸Ãë0ÜÃ33 œÃ¸ˇÏ@ ˚
  10107. ÃÃ√ò0Ãà 33 à ˚@  _† ˝ˇ¸ÃÃ…ô0ÃÃL33 ÃL¸ˇ@Ï@ ¸áœá0œáå·„«å˚@ _ø˚˝ˇ¸Ú¸ˇ˜Ï@„ @„ @„ „ˇ¸
  10108. @Â
  10109. @Â
  10110. @Â
  10111. @Â
  10112. @Â!
  10113. @Â@å
  10114. @ÂÄL
  10115. @·Ï
  10116. @Â!
  10117. @Â!
  10118. @Â!
  10119. @Â?
  10120. @Â
  10121. @Â
  10122. @¡¸
  10123. @¡¸
  10124. @Â
  10125. @Â
  10126. @Â
  10127. @Â
  10128. @Â"@@Äqƒ`IJ@˝!
  10129. @@Ä"ä$ ˝Ä˛@˝#!@ß8ò ÇŒ&eª7Ã≥É,¡ΔY–L≥#@˛§Ń$))ñ$îÑ탱!!bJǃÄ#!@Ù§ºÄ$ È/Ù$îúíɰ·'BJéáÄ#!@§†"ä$%)(Ñ$î§íÄѰ)BEÑ#!@8òqƒÓ&d$îúLᆡ'A≈É@ È@ È
  10130. @¡¸
  10131. @ÂDL
  10132. @Â!@@      Ä8‚0˙¸DL!@@˛      ÄE"¸#@Ãã1éΔpgs¡Ã A g#å≥˛DL#!@RQJP    !  • í@‚îÄ"RƒÄ#!@^QCà   ' r#° í@tóÄ"^áÄDL#@P!J    ) í$• íEîî"PÑ˛#@Ã!1ú'qô L8‚ w"LɲDL
  10133. @Â
  10134. @ÂDL
  10135. @Â
  10136. @ÂDL
  10137. @Â@˝A˚      @˝DL@˝A˚     ˝@˚#!@≤N·Δ0v2ÃΔpt2›õåÊY√p0DL#!@JPA)    HIK    !H"§ÇKJBIbH#!@JLA/    HIJ    'H"§ÇzJNIAÅH8DL#!@JBA(    HIJ    )H!DÇBJRI@AHH#!@I‹!Δ    0I2 'HC2JN&CÅH8DL
  10138. @Â
  10139. @ÂDL
  10140. @Â
  10141. @ÂDL
  10142. @Â@«@ÏDL@(¢@Π   @ Aúf‡ÌDL    @»BRêÌ    @(BrêÌDL    @(¢BRíêÌ    @«AíríÌDL
  10143. @Â@˜˙›‹¯DL@˜˙wt¯@˜˙›‹¯DL@˜@˚¯@˜¿˚¯DL@˜@?˛¯@˜¿˘¿¯DL@˜@ x¯@˜¿ˇ¿¯DL@˜@p¯@˜¿0?û¯DL@˜@‡g„¿¯@˜¿x·¸p¯DL@˜@ˇ√˘«ˇ¯@˜√üˆ9ú¯DL@˜F˜‡ˇÜî¯@˜ƒOx?¸ú¯DL@˜Lˇ¯‘¯@˜‹wˇÒˇÄ‹¯DL@˜X√ˇ¸¿‘¯@˜‹CˇˇÉ¯1ú¯DL@˜MŎˇ‡Óaî¯@˜«{ˇ¸?A‹¯DL@˜@ˇˇÛ‘¯@˜¿ˇˇÛˇ‹¯DL@˜@=ˇ˛›î¯@˜¿ˇ˛˛¯DL@˜@Ô˙û¯@˜¿˛ˇ˚æ¯DL@˜@˛ˇ~¯@˜¿˝ˇ¸¯DL@˜@˝|~¯@˜¿¸2¯DL@˜@¸¯ˇ¸@˜¿¸¯ @˜@¸¯ @˜¿¸¯? @˜@˚¯! @˜˙›‹¯! @˜˙wt¯! @˜˙›‹¯·Ï
  10144. @ÂÄL
  10145. @Â@å
  10146. @Â!
  10147. @Â
  10148. @Â
  10149. @Â
  10150. @ „ˇ¸@ˇˇëÎ @Ä¿ƒÎDF AÄ¿ëβ BÄ¿ƒÎDFÑÇ D¯¿ëÎ>DÉÏH¿ƒÎDF $Ç,P¿ëΠÇ,P¿ƒÎDF Ç,H¿ëΠ$˛,D¯¿ƒÎDF>D ,BÄ¿ëÎÑ ,AÄ¿ƒÎDF ,@Ä¿ëÎ?Ï@ˇˇƒÎDF „ˇ¸?„ˇ¸flflfl†Éˇ@ˇ ˇˇˇˇ@
  10151. ˇ·ˇ‚7^
  10152. 4*\˜, Palatino
  10153. .+l"CHAPTER €`)\1,     Helvetica
  10154.     (@lThe Edition Manager4⁄*˙¯
  10155. (‡*1 )-c)10
  10156.     )9%Publishers, Subscribers, and Editions
  10157. *Draft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯
  10158. g*w¯4g*w¯"g*_
  10159. ˇ·ˇ‚7^
  10160.     °dONLNdˇˇ(dl
  10161. Figure 1-7°dONLNd\Æga)B)Edition Manager commands in the Edit menu
  10162. °dONLNd*)l5ˆ(2lRThe Subscriber Options menu command should toggle with the Publisher Options menu °dONLNd|5lA+* )command. When a user selects a subscriberj`°dONLNd•5+A‚)ø&, the Subscriber Options menu command °dONLNdÀAlMÇ(Jl=should appear in the menu and when a user selects a publisher$‡°dONLNdAÇMÍ(JÇ, the Publisher Options °dONLNd MlY€(VlLmenu command should appear in the menu. In addition, you may support a Show °dONLNdlYle{* Bor÷@°dONLNdoY{eP),ders menu command that toggles with Hide Bor@°dONLNdõYQeı)÷'ders to display or hide all publishers °dONLNd¬elqæ(nland subscriber bor« °dONLNd‘eæq))Rders within documents. ≤`°dONLNdÎe)q/)kYr‡°dONLNdÏe/q™)ou may also support a Stop {¿°dONLNde™q·){
  10163. All Editions °dONLNdql}Ã(zlmenu command to prp°dONLNd&qÃ}ı)`Covide a method for temporarily suspending all update activity in a °dONLNdi}lâÛ(ÜlSdocument. When the user chooses this command, you should place a checkmark next to °dONLNdºâlïw* it. } °dONLNd¿âwï}) Y=†°dONLNd¡â}ï)%ou should also stop all publishers fr. °dONLNdÊâïÌ)û0om sending data to editions and all subscribers °dONLNdïl°s(ûlfrò‡°dONLNdïs°á)om r'`°dONLNdïà°∑)Beceiving new editions. When the user chooses this command again, r̰dONLNd^ï∑°Á(û∑
  10164. emove the °dONLNdh°l≠7(™l,checkmark and update any subscribers that arO°dONLNdî°8≠k)Ã
  10165. e set up to rÁ¿°dONLNd°°k≠ƒ)3eceive new editions °dONLNdµ≠lπ®(∂l
  10166. automaticallyÚ °dONLNd¬≠ßπ©);.°dONLNdƒølÀé(»lIf you fiJ‡°dONLNdÕøèÀæ)#Fnd that you need all of the available space in the Edit menu for your °dONLNdÀl◊(‘l"application’s commands, you may cr °dONLNd5À◊E)£
  10167. eate a hierar'¿°dONLNdBÀE◊È)6$chical menu for the Edition Manager °dONLNdf◊l„W(‡l2menu commands. If you choose to implement this strê@°dONLNdò◊W„n)Îuctur °dONLNdù◊o„Ì)e, you should allow users to °dONLNd∫„lÔC(Ïl,access the Edition Manager menu commands thr´¿°dONLNdÊ„CÔÏ)◊"ough a Publishing menu command in °dONLNdÔl˚(¯l$the Edit menu. Because this menu str&`°dONLNd,Ô˚')§uctur¨@°dONLNd1Ô'˚fi),e is not as accessible to users, you should °dONLNd]˚lJ(l3implement it only if you have no other alternative.°dONLNdë
  10168. lÑ*FigurR¿°dONLNdñ
  10169. Ñò)e 1-8@°dONLNdõ
  10170. òí)4 shows the Edition Manager menu commands in a hierar´¿°dONLNdœ
  10171. ì÷)˚chical menu strİdONLNdfi
  10172. ◊Ó)Ducturà`°dONLNd„
  10173. Óı)e.
  10174. wl¯4wl¯†Ç
  10175. wl«ò(
  10176. –.
  10177. œxm÷ÎΠ   ˝ˇÚ    ˝ˇÚ    ˝ˇÚ    ˝ˇÚ
  10178. ‡¸ŒÚ
  10179. Á¸˛Ú
  10180. Á‡Ã?Ú
  10181. ÁÃŒÚ
  10182. ·ÃŒÚ
  10183. ÁÃŒÚ
  10184. ÁÃŒÚ
  10185. ÁÃŒÚ
  10186. ‡‡œ?Ú    ˝ˇÚ    ˝ˇÚ    ˝ˇÚ    ˝ˇÚ    ˝ˇÚÔˇ¿@Ô@@Ô@@Ô`@fˆ«‡`@fˆ% ``@f|><˜% ``@˝f˜¿¿`@˝f˜Ä`@˝f˜√`@˝f˜%&`@˝f˜%&`@<f><˜«‡`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`jÔ™‡@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@<0ˆΔ``@b0ˆ%&``@`fxˆ%&``@`f0ˆΔ``@`f0ˆ¿`@`f0ˆΔ``@`f0ˆ%&``@bf0ˆ%&``@<>ˆΔ``@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`
  10187. @<Ù√¿`
  10188. @bÙ%& `@`<|f˜%&`@`˛f˜Δ`@`˛f˜`@`˛f˜Δ`@`˛f˜%&`@b˛f˜%& `@<<|>˜√¿`
  10189. @˛`Ù`
  10190. @˛`FÙ` @˝<Ù`@Ô`@Ô`@Ô`@Ô`@|`˜Δ``@f`˜%&``@f<8Ò‡¯%&``@fFdc0¯Δ``@|>pc0¯``@`f8c¯Δ``@`fc˜%&``@`fLc¯%&@`@`>81‡¯«Ä`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô` @<`Ú` @b`Ú`@`c√Δ¿ı`
  10191. @`fdgÙ`
  10192. @`fcÊÙ`
  10193. @`gÊfÙ`
  10194. @`ffÙ`
  10195. @bf&fÙ`
  10196. @<c√ÊÙ`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`
  10197. @8¿ Δ`˚√¿`
  10198. @d¿ f`˚%&``
  10199. @`x«áf`˚%&``@p˛Ãåf`˚Δ``@8˛Ã Ê`˚‡`
  10200. @¸œÃ f`˚Δ``
  10201. @ ¿Ã f`˚%&``
  10202. @LƒÃLåf`˚%&``
  10203. @8x«áf`˚Δ``@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`jÔ™‡@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@<˛¿|`f¿¸`@b˛¿f``¿¸`@`lÒ„¿ff|f8¯xÿ˛`@`qôΔ`˝fdÃDz`    @`aò¯Δ`|˛fpÃÿ˛`    @`a˘ò«‡`˛f8ø¿˛`    @`aÅòΔ`˛fÿ¿˛`    @baâòΔ `˛fLÃ√3`@<`¯c¿`>|f8Ãx√3`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô` @8¿ ¿Ä˙`@d¿˛¿˘` @`ïp„l¯x˙` @pÃÃ…ìåÃÃ3˙` @8ÃÃ·É ÃÃ3˙` @ÃÃqÉ Ã¸3˙` @ ÃÃ9É Ã¿3˙`@LÃÃôì Ã330¸`@8|¯p„ ¯x30¸`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@8¿ ¿¿˝`@d¿˛¿3¸`@`ïp„l¯xÿ3><«èá`@pÃÃ…ìåÃÇ33˛ÃÄ`@8ÃÃ·É Ãÿ33ÃÃŒ`@ÃÃqÉ Ã¸¿33Ãë`@ ÃÃ9É Ã¿¿33ÃÃ√Ä`@LÃÃôì ÿ33ÃÃ…ôò`@8|¯p„ ¯x¿> «å«ò` @ˆ0˚` @ˆ0˚`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`jÔ™‡@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@Ô`@8¿˛xÿ˛0˝`@d¿˛ƒ¿¿˛0˝`@`¯xÿ¿Ã¯¯xxŸ˝`@p˛Ã¿¿˝Ãå„0˝`@8˛Ã¿¿˝Ã|√0˝`@˛Ã¿¿¸Ã√0˝`@ ˛Ã¿¿¸Ã√0˝`@L˛Ãă¸Ã√0˝`@8Ãxˇxï¯x|¡˝` @˘¿¯` @˘¿¯`@Ô`@Ô`Ôˇ‡Ôˇ‡ÎÎÎΆɡÃ@ˇ ˇˇˇˇ@
  10204. ˇ·ˇ‚7^
  10205. 4H\, Palatino
  10206. .+ä"CHAPTER €`)\1,     Helvetica
  10207.     (@äThe Edition Manager4⁄ä˙(‡ä%Publishers, Subscribers, and Editions
  10208. ~¿(‡1
  10209. ‡)-a¿)11
  10210. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿
  10211. gHw4gHw"gH_
  10212. ˇ·ˇ‚7^
  10213.     °dONLNdˇˇ(dä
  10214. Figure 1-8°dONLNd\Ãg”)B:Edition Manager commands under the Publishing menu command
  10215. °dONLNd;
  10216. ä˛(äRFor each publisher or subscriber within an open document, you must have a section °dONLNdçä"ç* rE°dONLNdéé"†)ecorπ`°dONLNdí†"„)d and an alias rf`°dONLNd¢‰"ˆ)Decor⁄¿°dONLNd¶ˆ"9)d. The section r_¿°dONLNd∂:"L)Decor‘ °dONLNd∫L"œ)d contains a time stamp that r °dONLNdÿ–"‚)ÑecorçİdONLNd‹‚"ˇ)ds the °dONLNd„"ä.ˆ(+äversion of the data that rÓ¿°dONLNd˝"ˆ.ã)l$esides in the section. The section ri°dONLNd!"å.û)ñecor›`°dONLNd%"û.⁄)d also identifij†°dONLNd4"€.ˆ)=es the °dONLNd;.ä:@(7ä+section as either a publisher or subscriberñ`°dONLNdf.@:)∂0, and it establishes a unique identity for each °dONLNdñ:äF(Cäpublisher or subscriberÓ‡°dONLNd≠:ÔF,)e. The section rX °dONLNdº:-F?)>ecorÃİdONLNd¿:?F^)d does Ä °dONLNd«:_Fl) not”`°dONLNd :lF )
  10217. & contain the data within the section. °dONLNdFäR∑(Oä The alias rİdONLNd˚F∏R ).ecorLJ°dONLNdˇF RÁ)d is a r    °dONLNdFËR¯)eferµ °dONLNd F¯R~) ence to the edition container frg°dONLNd+FR
  10218. )áom the document that contains °dONLNdIRä^¨([äthe corrz¿°dONLNdQR¨^i)"+esponding publisher or subscriber section. °dONLNd}däpû(mäTher¿°dONLNdÅdüpØ)e ar`°dONLNdÖdØp)Oe special options associated with publishers and subscribers within documents. °dONLNd‘pä|ê(yäY@İdONLNd’pê|·)Lour application can use the publisher and subscriber options dialog boxes prœÄ°dONLNd!p·|(y·
  10219. ovided by °dONLNd+|äà¢(Öä?the Edition Manager to make these choices available to the userË¿°dONLNdj|°à(Ö°. For example, a user can °dONLNdÑàäî    (ëäVselect Open Publisher within the subscriber options dialog box to access the document °dONLNd⁄î䆈* containing the publisher»`°dONLNdÚîı†˙)k. ö¿°dONLNdÙî˙†)Y[@°dONLNdıî†
  10220. )?our application can also allow a user to cancel subscribers or °dONLNd4†ä¨∞(©äApublishers within documents, specify when to update an edition fr`°dONLNdu†±¨Û(©±om a publisherø¿°dONLNdɆڨ)A, or °dONLNdà¨ä∏Ã(µäHspecify when to update a subscriber with a new edition. These options ar∫†°dONLNd–¨Ã∏(µà e described °dONLNd‹∏äƒfl(¡älater in this chapter^‡°dONLNdÒ∏flƒ·)U.
  10221. wäÚ4wäÚ†Ç
  10222. wäÚJò$⁄(⁄'xãÚ:››¸ˇÄ‰¸ˇÄ‰¸ˇÄ‰¸ˇÄ‰
  10223. ˇÉÛ9ˇÄ‰
  10224. ˇüÛ˘ˇÄ‰
  10225. ˇüÉ0ˇÄ‰
  10226. ˇü39ˇÄ‰
  10227. ˇá39ˇÄ‰
  10228. ˇü39ˇÄ‰
  10229. ˇü39ˇÄ‰
  10230. ˇü39ˇÄ‰
  10231. ˇÉÉ<ˇÄ‰¸ˇÄ‰¸ˇÄ‰¸ˇÄ‰¸ˇÄ‰¸ˇÄ‰Úˇ‡Ó    ÄÛ Ó    ÄÛ Ó    ÄÛ0ÓÄà ˙ c0ÓÄà ˙ê00ÓÄï|x˚ê00ÓÄ˝Ã˚‡`0ÓÄ˝Ã˚Ä¿0ÓÄ˝Ã˚·Ä0ÓÄ˝Ã˚ì0ÓÄ˝Ã˚ì0ÓÄxÃ|x˚ c0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ’ÛUpÓ    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0ÓÄx`˙ c00Óă`˙ì00ÓÄ¿Ã˙ì00ÓÄ¿Ã`˙„00ÓÄ¿Ã`˙Ň0ÓÄ¿Ã`˙„00ÓÄ¿Ã`˙ì00ÓăÃ`˙ì00ÓÄx|0˙ c00Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0ÓÄx¯ a‡0Óă¯ì0ÓÄ¿x¯Ã˚ì0ÓÄ¿˛Ã˚„0ÓÄ¿˛Ã˚É0ÓÄ¿˛Ã˚„0ÓÄ¿˛Ã˚ì0Óă˛Ã˚ì0ÓÄxx¯|˚ a‡0ÓIJ¿ ¯0ÓIJ¿å¯0Ó
  10232. Ä˝x¯0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Óį¿˚ c00ÓÄÿ˚ì00ÓÄÃxq„¿¸ì00ÓÄÃå»Δ`¸„00Óį|‡Δ`¸É00ÓÄ¿Ãp«‡¸„00ÓÄ¿Ã8Δ˚ì00ÓÄ¿ÃòΔ ¸ì 0ÓÄ¿|pc¿¸ c¿0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0ÓÄpÄå¿ a‡0ÓÄ»Ä ÿì00ÓÄ¿Òè< ÿì00ÓÄ·˛ô     ÿ„00ÓÄqôôòÿÉ0ÓÄ9˘üò ÿ„00ÓÄÅò ÿì00ÓÄôâòô ÿì00ÓÄpÒè ÿ c00Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ’ÛUpÓ    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó    ÄÛ0Ó ÄÙÔˇÄ Ûˇ¸ÔÄ Ûˇ¸Ô¿ Ùˇ˜¸Ô¿"    ˇˇˇ?3˛~˝ˇÛ¸¿ ¿` ¸¿!ˇˇ3ˇ??˛¸ˇÒ¸  ` ¸¿%#ˇˇ333é`ˇˇ¸œ<fgΔcèáçÄ¿#ˇˇ˝36˛f ˇˇ|ëåf˝fLÃŒ˛¿%ˇˇ˛3˛fˇˇ<èåfΔffg ÃÃ˛¿%ˇˇ?˛3é˛fˇˇ|ôå~ffcåœÃ˛¿%ˇˇ?˛3Δ˛fˇˇ¸å`ffaÃà ˛¿#ˇˇ?˛3˝fˇˇÒ¸&ôåbffdÃÃL30¿%#ˇˇ?É3éffpˇˇÛ¸ΔÜ<ÁΔcå«å30¿¯ˇ˛ˇˇ˜¸Ô¿¯ˇÓ˛ˇ¸Ô¿¯ˇ˝ˇ¸Ô¿ Ûˇ¸Ô¿ ÄÙÔ¿ ÄÙÔ¿ ÄÙÔ¿ÄÙÄ ˛Ã¯˙¿ÄÙ@ ˛ `˙¿ÄÙ  œá6œáÄa‡˚¿ÄÙ  ÃÃô8Ãÿc0˚¿ÄÙ åÃŒ0Ãÿc0˚¿’ÙU TÃë0Ü¿c0˚¿ÄÙ ÃÃ√ò0ÃÃc0˚¿ÄÙ
  10233. ÃÃ…ô0ÃÃ@c33¸¿ÄÙ
  10234. áœá0œáÄa„3¸¿ ÄÙÔ¿ ÄÙÔ¿ ÄÙÔ¿ ÄÙÔ¿ ÄÙÔ¿ ÄÙÔ¿ ÄÙÔ¿#ÄqIJÒòIJ
  10235. d¿` ‡å¸¿# Ä…ÄâÄIJ
  10236. d` 0ĸ¿%#Ä¡ÒôÅÅôÒÒ≥‰fgΔcèáçÉ3„Ãx¯p¿#Ä·˛ôÅÅ˝ôΔd˝f
  10237. LÃŒ31åÃû¿%Äq˛ôÅŞôò˘ÜdΔffg ÃÃ31åÃÇ¿#Ä9˛ôÅŸôÜdffcåœÃ31åÃÃp¿#IJôÅŸôÜdffaÃà 31åÃÃ8¿"Ä˝ôâ¸ôÜdffdÃÃL31åÃÃôôÄ¿%#ÄqòÒ˛ÒôÒ˘É‰ÁΔcå«å„‡ÃxÃqôÄ¿Ä˙Ä˝˜˙¿Ä˙Ä˝˜˙¿ ÄÙÔ¿ ÄÙÔ¿‡ˇ¿?·ˇ¿››››†Éˇ†@ˇ ˇˇˇˇ@
  10238. ˇ·ˇ‚7^
  10239. 4⁄*˙¯,     Helvetica
  10240. .(‡*1 )-c)12
  10241.     )9Using ◊P)The Edition Manager
  10242. (ÔlDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/92, Palatino("lCHAPTER )_1
  10243.     ˇˇ—ÚˇÆ°dONLNd8lCº(@lThe Edition Managerˇˇˇˇˇˇ≠>(@Û1
  10244. ]*x¯4^*x¯
  10245. â*ë¯4ä*믠ä*ä˛
  10246. ˇ·ˇ‚7^
  10247. ˇˇ£‰°dONLNdv*àZ(Ñ*Using ¯°dONLNdv[à˚)1The Edition Managerˇˇˇˇˇˇ⁄|(ÑÓ1
  10248. °dONLNd.ôl•B(¢l0This section describes how your application can ,
  10249.  
  10250. Zapf Dingbats
  10251. °dONLNd_Ælµq*n
  10252. °dONLNda´x∑{) rE°dONLNdb´|∑ô)eceive ¬`°dONLNdi´ô∑›)Apple events fr„°dONLNdx´›∑H)Dom the Edition Manager
  10253. °dONLNdè¿l«q(Δln
  10254. °dONLNdëΩx…¬) set up a section r¿°dONLNd£Ω¬…‘)JecorÙ °dONLNdßΩ‘…
  10255. )
  10256. d and alias rO¿°dONLNd¥Ω …)7ecorƒ °dONLNd∏Ω…’)(d for open documents containing sections
  10257. °dONLNd·“lŸq(ÿln
  10258. °dONLNd„œx€#) &save a document that contains sections
  10259. °dONLNd
  10260. ‰lÎq(Íln
  10261. °dONLNd ·xÌ%) &open a document that contains sections
  10262. °dONLNd3ˆl˝q(¸ln
  10263. °dONLNd5Ûxˇ{) rE°dONLNd6Û|ˇfi)ead and write sections
  10264. °dONLNdMlq(ln
  10265. °dONLNdOxÄ) crµ@°dONLNdQÄ))&eate a publisher within a document, cr3@°dONLNdw*ñ)™eate its edition container‚ °dONLNdëïÓ)k, and write data to it
  10266. °dONLNd®l!q( ln
  10267. °dONLNd™x#Ä) crµ@°dONLNd¨Ä#9))eate a subscriber within a document and r¿°dONLNd’:#v)∫ead its data fr_‡°dONLNd‰v#≥)<
  10268. om an edition°dONLNdÚ)l5r(2lTµ¿°dONLNdÛ)q5Ò)To begin, you must determine whether the Edition Manager is available on your system .°dONLNdG5lA§(>l
  10269. by using the ,
  10270. Courier°dONLNdT5§AŒ)8Gestalt°dONLNd[5ŒA`)*# function. The Gestalt selector is °dONLNd~5`Afi)ígestaltEditionMgrAttr°dONLNdì5fiA‡)~ °dONLNdîAlMØ(Jl('edtn'). If the °dONLNd•AØMfl)Cresponse°dONLNd≠AflM)0  parameter rR`°dONLNdπAMy)8eturns 1 in the bit defiR`°dONLNd—AyM™)b ned by the °dONLNd‹MlY¸(VlgestaltEditionMgrPresent°dONLNdÙM¸Y∫)ê, constant (bit 0), the Edition Manager is prR`°dONLNd M∫Y÷)æesent. °dONLNd(_lkÍ(hlIf the Edition Manager is prR`°dONLNdD_Íkå)~%esent, load it into memory using the R`°dONLNdi_åkÊ)¢InitEditionPackR`°dONLNdx_ÊkË)Z .°dONLNdyklw⁄(tlPfunction. This function determines whether your machine has enough space in the °dONLNd…wlÉA* /system heap for the Edition Manager to operate..°dONLNd˘èlõˆ*err := InitEditionPack;°dONLNdßl≥à*If the °dONLNdßà≥‚)InitEditionPack°dONLNd'ß‚≥)Z  function rR`°dONLNd2ß≥+),eturns R`°dONLNd9ß+≥I)noErrï°dONLNd>ßH≥Í)$, you have enough space to load the .°dONLNdb≥løÌ(ºlYpackage. If you do not have enough space, the application can either terminate itself or °dONLNdªølÀl* 9continue with the Edition Manager functionality disabled.
  10271. *ˆ¯4Ò*ˆ¯ ÒlÒ¯
  10272. ˇ·ˇ‚7^
  10273. ˇˇ◊ˇ◊°dONLNdıfll¥*$
  10274. Receiving ˝†°dONLNdˇfl≥#)GApple Events FrPê°dONLNdfl$Ã)qom the Edition Managerˇˇˇˇˇˇ®)Ã1
  10275. °dONLNd%ˆlh(ˇl7Applications that use the Edition Manager must support 釰dONLNd\ˆh¡)¸Apple events. This rs °dONLNdpˆ¡ÿ)Yequirä`°dONLNduˆÿ˜)es that °dONLNd}lÒ( lyour application support the r Ä°dONLNdõÒ)Öequir·¿°dONLNd†ì)ed Open Documents event and 4†°dONLNdºîÛ)åApple events sent by °dONLNd—l«(lthe Edition Manager√İdONLNd‰ΔÏ)Z
  10276. . See the İdONLNdÓÌΔ)'/Apple Event Manager chapter in this volume for °dONLNdl&±(#linformation on #‡°dONLNd,±&)EApple events. °dONLNd;,l8¥(5lJApple events sent by the Edition Manager arrive as high-level events. The .°dONLNdÖ8lDÆ* EventRecord°dONLNdê8ÆDÓ)B data type defPİdONLNdû8ÓD3)@ines the event r"‡°dONLNdÆ83DE)Eecorı@°dONLNd≤8DDM)d.ˇ@ˇ ˇˇˇˇ@
  10277. ˇ·ˇ‚7^
  10278. 4*\˜, Palatino
  10279. .+l"CHAPTER €`)\1,     Helvetica
  10280.     (@lThe Edition Manager4⁄*˙¯
  10281. (‡*1 )-c)13
  10282.     )9Using ◊P)The Edition Manager
  10283. (ÔlDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯,
  10284. Courier
  10285. .°dONLNd\lhÿ(elTYPE EventRecord =°dONLNdj~v¢+RECORD°dONLNdxêÑÆ+what:°dONLNd&xÿÑ)HInteger;°dONLNd2x ÑÜ)H{kHighLevelEvent}°dONLNdFÜêí¿(èêmessage:°dONLNdRÜÿí)HLongInt;°dONLNd^Ü íP)H{'sect'}°dONLNdiîê†Æ(ùêwhen:°dONLNdrîÿ†)HLongInt;°dONLNd~¢êÆ¥(´êwhere:°dONLNdà¢ÿƸ)HPoint;°dONLNdí¢ Æ¬)H{'read', 'writ', 'cncl', } °dONLNdº∞ ºV*    { 'scrl'}°dONLNd»æê Ã(«ê
  10286. modifiers:°dONLNd÷æÿ )HInteger;°dONLNd·Ã~ÿñ(’~END;.°dONLNdʉl3(Ìl+The Edition Manager can send the following C °dONLNd‰3p)«
  10287. Apple events:,
  10288.  
  10289. Zapf Dingbats
  10290. °dONLNd˘lq(ˇln
  10291. °dONLNd!ˆxÛ) Section Read events ('sect' 'rñ†°dONLNd?ˆÛ){ead')
  10292. °dONLNdE lq(ln
  10293. °dONLNdGx§)     Section W-‡°dONLNdP§    ),rite events ('sect' 'writ')
  10294. °dONLNdll$q(#ln
  10295. °dONLNdnx&
  10296. ) %Section Cancel events ('sect' 'cncl')
  10297. °dONLNdî/l6q(5ln
  10298. °dONLNdñ,x8®) Section Scr`@°dONLNd°,®8)0oll events ('sect' 'scrl')°dONLNdº>lJÓ(GlEach time your application crê@°dONLNdŸ>ÓJ{)Ç!eates a publisher or a subscriberë¿°dONLNd˙>{J›)ç, the Edition Manager °dONLNdJlVo(SlrE°dONLNdJpV‰)Xegisters its section. When an edition is updated, the Edition Manager scans its list to °dONLNdiVlbå(_llocate rü °dONLNdqVåb©) egisterÓ@°dONLNdxV©b)ed subscribers. For each r°dONLNdíVb6)pegister? °dONLNdôV7bæ)!ed subscriber that is set up to rá°dONLNd∫Væb€)áeceive °dONLNd¡blnˆ(klupdated editions automaticallyª@°dONLNdflbınI)â, your application r5İdONLNdÛbJnÃ)Ueceives a Section Read event. °dONLNdtlÄG(}l2If the Edition Manager discovers that an edition fim@°dONLNdEtHĆ)‹le is missing while rK†°dONLNdZt†Ä’)X
  10299. egistering a °dONLNdgÄlåñ(âl    publisherÓ‡°dONLNdpÄïå´)), it crŒ‡°dONLNdwÄ´å)eates a new edition fi†°dONLNdçÄ    å≥)^&le and sends the publisher a Section Wß°dONLNd≥Ä≤å‡)© rite event. °dONLNd¿ílû†(õl
  10300. When you rΩ °dONLNd í†ûß)4<eceive a Section Cancel event, you need to cancel the specifiœ`°dONLNdíßû(õßed section. Note °dONLNdûl™¢(ßl
  10301. that the curr‚İdONLNd%û¢™Í)6Hent Edition Manager does not send you Section Cancel events, but you do °dONLNdm™l∂ô(≥l
  10302. need to pr`°dONLNdw™ô∂)-ovide a handler for futurÒİdONLNdê™∂<)m e expansion.°dONLNdùºl»Ù(≈lZIf the user selects a subscriber within a document and then selects Open Publisher in the °dONLNd˜»l‘n* ;subscriber options dialog box, the publishing application rg °dONLNd2»n‘(—neceives the Open Documents °dONLNdM‘l‡b(›l5event and opens the document containing the publisheri¿°dONLNdÇ‘b‡Ù)ˆ". The publishing application also °dONLNd§‡lÏo(ÈlrE°dONLNd•‡pÏ…)eceives a Section Scræ°dONLNd∫‡…Ï)Yoll event. ScrFİdONLNd»‡Ïñ)9$oll to the location of the publisherw`°dONLNdχñÏÚ)î, display this section °dONLNdÏl¯ù(ıl on the userb°dONLNdÏû¯¥)2’s scrXİdONLNdÏ¥¯)een, and turn on its bor(İdONLNd,ϯ))gderC °dONLNd/Ï)¯.). °dONLNd2˛l
  10303. }(lSee ”°dONLNd6˛}
  10304. x)4“Opening and Closing a Document Containing Sections”£`°dONLNdj˛y
  10305. ‚)¸ later in this chapter for °dONLNdÖ
  10306. l€(ldetailed information on r• °dONLNdû
  10307. €,)oegistering and unrı`°dONLNd∞
  10308. ,Ë)Q,egistering a section and writing data to an °dONLNd‹l"°(l
  10309. edition. See `°dONLNdÈ¢"])6(“Using Publisher and Subscriber Options”߆°dONLNd]"Δ)ª later in this chapter for °dONLNd,"l.D(+l0information on publisher and subscriber options.°dONLNd]4l@â*After rfi¿°dONLNdd4â@Ω) eceiving an ,¿°dONLNdp4æ@s)5'Apple event sent by the Edition Managerl °dONLNdó4s@ô)µ
  10310. , use the ¯‡°dONLNd°4ô@”)& Apple Event °dONLNd≠@lLØ(IlKManager to extract the section handle. In addition, you must also call the .°dONLNd¯LlXfi* IsRegisteredSection°dONLNd LfiX¨)r/ function to determine whether the section is rR`°dONLNd:L¨XÀ)Œegister$¿°dONLNdALÀXÔ)
  10311. ed. It is .°dONLNdKXld(al'possible (due to a race condition) to r6°dONLNdrXdπ)§(eceive an event for a section that you r{¿°dONLNdöXπd€)©ecently °dONLNd¢dlpΩ(mldisposed of or unr™ °dONLNd¥dΩp⁄)Qegister˘@°dONLNdªd⁄p8)ed. One way to ensur†°dONLNdœd9pé)_e that an event corrÛ`°dONLNd„dçpfl)Tesponds to a valid .°dONLNdˆpl|»(ylsection is to call the °dONLNd    
  10312. p»|:)\IsRegisteredSection°dONLNd     p:|ë)r function after you rR`°dONLNd    5pë|Ô)Weceive an event. The .°dONLNd    J|là@(Öl-Apple Event Manager chapter in this volume prT °dONLNd    w|@àÀ)‘ovides detailed information on ¸`°dONLNd    ñ| àÁ)äApple °dONLNd    úàlî∂(ëlEvent Manager rv`°dONLNd    ´à∂î÷)Joutinesı¿°dONLNd    ≤à÷î€) . .°dONLNd    µ†l¨P(©l&err := IsRegisteredSection (sectionH);ˇ í@ˇ ˇˇˇˇ@
  10313. ˇ·ˇ‚7^
  10314. 4H\, Palatino
  10315. .+ä"CHAPTER €`)\1,     Helvetica
  10316.     (@äThe Edition Manager4⁄ä˙(‡äUsing ◊P)The Edition Manager
  10317. ~¿(‡1
  10318. ‡)-a¿)14
  10319. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿
  10320. °dONLNd\äh∏(eä Listing 1-1 @°dONLNd \πh,)/ illustrates how to use the ~°dONLNd'\,h)s1Apple Event Manager and install an event handler °dONLNdXhät(qäto handle Section Read events. Ɇ°dONLNdwht)âYD °dONLNdxhtΔ)'ou can write similar code for Section W2 °dONLNdühΔt¯)≠
  10321. rite events, °dONLNd¨täÄ∫(}ä Section Scr`@°dONLNd∑t∫Äa)0'oll events, and Section Cancel events. 
  10322. ¢H¶4£H•"£Ha
  10323. ˇ·ˇ‚7^
  10324.     °dONLNdˇˇ(†ä Listing 1-1°dONLNdflòŒ£·)DFAccepting Section Read events and verifying if a section is registered,
  10325. Courier
  10326. .°dONLNd&Øäª∞(∏ä1{The following goes in your initialization code.}°dONLNdXΩä…˛*>MyErr := AEInstallEventHandler(sectionEventMsgClass {'sect'}, °dONLNdõÀ“◊fi+H  °dONLNdüÀˆ◊)$  °dONLNd•À>◊Ê)H sectionReadMsgID {'read'}, °dONLNdΔŸ“Âfi(‚“  °dONLNdŒŸ>ÂÚ)l @MyHandleSectionReadEvent, 0,°dONLNd˜Á>Ûn* FALSE);°dONLNdäÚ( ä<{This is the routine the Apple Event Manager calls when a } °dONLNd>ä>*{ Section Read event arrives.}°dONLNd^-ä9∞*1FUNCTION MyHandleSectionReadEvent(theAppleEvent, °dONLNdõ;PG»+Δ reply: AppleEvent; °dONLNd¥I“U‰(R“   °dONLNd∫IU)6  °dONLNd¿IPUÏ)H refCon: LongInt) : OSErr;°dONLNd€Wäcú(`äVAR°dONLNd‡eúqΔ+getErr:°dONLNdÎe‰q)HOSErr;°dONLNdÛsú“(|ú    sectionH:°dONLNds‰8)HSectionHandle;°dONLNdÅäç®(ääBEGIN°dONLNdèúõÊ+7{Get section handle out of Apple event message buffer.}°dONLNdOùú©
  10327. *=getErr := GetSectionHandleFromEvent(theAppleEvent, sectionH);°dONLNdèπú≈ *IF getErr = noErr THEN°dONLNdß«ú”∫*BEGIN°dONLNdØ’Æ·™+*{Do nothing if section is not registered.}°dONLNd‹„ÆÔû*(IF IsRegisteredSection(sectionH) = noErr°dONLNdÒ¿˝+9THEN MyHandleSectionReadEvent := DoSectionRead(sectionH);°dONLNdCˇú Ã(úEND ELSE°dONLNdM
  10328. ú∫*BEGIN°dONLNdUÆ'Ä+#MyHandleSectionReadEvent := getErr;°dONLNdz)ú5¥(2úEND;°dONLNd7äCD(@äEND; {MyHandleSectionReadEvent}°dONLNd†Sä_*B{The following routine should read in subscriber data and update }°dONLNd„aäm‰*{ its display.}°dONLNdÛoä{Ê*:FUNCTION DoSectionRead(subscriber: SectionHandle) : OSErr;°dONLNd.}äâ®*BEGIN°dONLNd7ã¿ó&+6{Your code here.}°dONLNdIôä•¢(¢äEND;°dONLNdRô‰•>)Z{DoSectionRead}ˇ∫@ˇ ˇˇˇˇ@
  10329. ˇ·ˇ‚7^
  10330. 4*\˜, Palatino
  10331. .+l"CHAPTER €`)\1,     Helvetica
  10332.     (@lThe Edition Manager4⁄*˙¯
  10333. (‡*1 )-c)15
  10334.     )9Using ◊P)The Edition Manager
  10335. (ÔlDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯,
  10336. Courier
  10337. .°dONLNd\lhí(el1{This is part of your Apple event–handling code.}°dONLNd2jlv‡*>FUNCTION GetSectionHandleFromEvent(theAppleEvent: AppleEvent; °dONLNd}xDѯ+ÿVAR sectionH: SectionHandle) :°dONLNd®ÜDíh*OSErr;°dONLNdØîl†~(ùlVAR°dONLNd¥¢~Æ¿+ ignoreType:°dONLNdƒ¢ÿÆ)Z    DescType;°dONLNdœ∞~º¿(π~ ignoreSize:°dONLNdfl∞ÿºˆ)ZSize;°dONLNdÂæl ä(«lBEGIN°dONLNdÏÃ~ÿå+-{Parse section handle out of message buffer.}°dONLNd⁄~Ê*GetSectionHandleFromEvent °dONLNd8ËêÙP+ := AEGetParamPtr( theAppleEvent,°dONLNddËhÙ»)ÿ{event to parse}°dONLNdyˆ¥¿(ˇ¥  °dONLNdˆ¸\)HkeyDirectObject,°dONLNdïˆh‘)l{Look for direct }°dONLNd∂h§*
  10338. { object.}°dONLNd√êú(ê  °dONLNdÀ¸P)ltypeSectionH, °dONLNdflhÚ)l{Want a SectionHandle }°dONLNd h,ò*{ type.}°dONLNd.ê:ú(7ê  °dONLNd.¸:>)l ignoreType,°dONLNd).h:Ú)l{Ignore type it could }°dONLNdO<hHí*{ get.}°dONLNdYJêVñ(Sê °dONLNd`J¸V>)l @sectionH, °dONLNdqJhV‡)l{Put SectionHandle }°dONLNdîXhdò*{ here.}°dONLNdüfêrñ(oê °dONLNd¶f¸rb)lSizeOf(sectionH),°dONLNdΩfhrÚ)l{size of storage for } °dONLNd„thÄ»*{ SectionHandle}°dONLNdˆÇêéñ(ãê °dONLNd˝ǸéD)l ignoreSize);°dONLNdÇhé‡)l{Ignore storage it }°dONLNd2êhúò*{ used.}°dONLNd;ûl™2(ßl!END; {GetSectionHandleFromEvent} 
  10339. —*◊¯4“*◊¯ “l“¯
  10340. ˇ·ˇ‚7^
  10341. ˇˇ◊.ˇ◊°dONLNd]¿l—}*&Crè °dONLNd_¿}—")eating the Section Recor˘†°dONLNdw¿"—M)•d and I°dONLNd}¿N—ù), Alias RecorI∞°dONLNdà¿ù—¶)Odˇˇˇˇˇˇ®)S1
  10342. °dONLNdä◊l„r(‡lY@İdONLNdã◊r„≈)our application is r—°dONLNdü◊≈„
  10343. )Sesponsible for crp‡°dONLNd∞◊„X)Ieating a section rÛ@°dONLNd¬◊X„j)Jecorg†°dONLNdΔ◊k„Æ)d and an alias r†°dONLNd÷◊Ø„¡)Decorâ°dONLNd⁄◊¡„Ô) d for each °dONLNd„lÔt(Ïl:publisher and subscriber section within an open document. °dONLNd ıl§*
  10344. The section rÈ@°dONLNd-ı§∂)8ecor]†°dONLNd1ı∑fl)    d identifi–°dONLNd;ıflª)(3es each section as a publisher or subscriber and prg‡°dONLNdnıº€)›ovides °dONLNdul
  10345. ã(
  10346. lidentifiV†°dONLNd}å
  10347. +) &cation for each section. The section r—İdONLNd£+
  10348. =)üecorE‡°dONLNdß>
  10349. Ë)'d does not contain the data within the °dONLNdŒ
  10350. l@(l5section; it describes the attributes of the section. †°dONLNd
  10351. AG)’YΔ °dONLNd
  10352. FÆ)our application must pr燰dONLNd
  10353. ØÌ)iovide its own °dONLNd)l%ã("lCmethod for associating the data within a section with its section rk@°dONLNdlã%ù("ãecorfl†°dONLNdpù%®)d. Õ¿°dONLNds®%Æ) Yé@°dONLNdtÆ%Ù)our application °dONLNdÑ%l1ç(.l    is also r@°dONLNdç%é1S)"/esponsible for saving the data in the section. °dONLNdΩ7lCõ(@l The alias fiV@°dONLNd…7úCÌ)0eld of the section rx@°dONLNd›7ÌCˇ)Qecorφ°dONLNd·7ˇCä)"d contains a handle to its alias r€Ä°dONLNd7äCú)ãecorO‡°dONLNd7ùC’)d. The alias r˙ °dONLNd7’CÁ)8ecornİdONLNd7ËC)d °dONLNdClOÅ(Llis a rj`°dONLNd!CÅOë)eferİdONLNd%CíO) ence to the edition container fr»`°dONLNdECOˆ)Ü0om the document which contains the publisher or °dONLNduOl[¿(Xlsubscriber section. R¿°dONLNdâO¿[Δ)TY@°dONLNdäOΔ[N)ou should be familiar with the °dONLNd©ON[é)à
  10354. Alias Manager∫`°dONLNd∂Oè[fl)A’s conventions for °dONLNd…[lgt(dlcrµ@°dONLNdÀ[tg¨)eating alias r‹‡°dONLNdŸ[¨gæ)8ecorQ@°dONLNd›[øg)ds and identifying fi†°dONLNdÚ[g∑)Z%les, folders, and volumes to locate fiA °dONLNd[∑gÒ)ûles that have °dONLNd&glsŸ(plbeen moved, copied, or r$ °dONLNd>g⁄sÔ)nestor߆°dONLNdCgÔs)ed fr%‡°dONLNdHgs:) om backup. °dONLNdTylÖw(Çl:When a user saves a document, your application should stor釰dONLNdéywÖ∞(Çwe all section rV¿°dONLNdùy±Ö√):ecorÀ °dONLNd°y√Ö„)ds and °dONLNd®ÖlëÜ(élalias r“¿°dONLNdØÖÜëò)ecorG °dONLNd≥Öôë≈) ds in the r|°dONLNdæÖ≈ë›),esourƒ@°dONLNd√Ö›ë)
  10355. ce fork. Corr
  10356. `°dONLNd–Öëk)8esponding section ro °dONLNd„Ökë})Vecor„İdONLNdÁÖ}ë∑)ds and alias r| °dONLNdıÖ∏ë );ecorİdONLNd˘Ö ë÷)ds °dONLNd¸ëlù“(ölshould have the same rÕ`°dONLNdë“ùÍ)fesour†°dONLNdëÎùü)*ce ID. This allows compatibility for futur˚`°dONLNdAëûùÀ)≥
  10357. e changes.°dONLNdL£lØÑ(¨lFigurR¿°dONLNdQ£ÑØò)e 1-9@°dONLNdV£òØñ)7 shows a document containing a publisher and subscriber≤ °dONLNdç£ñØæ)˛
  10358. , and the °dONLNdóØlª}(∏lcorr`°dONLNdõØ~ª‘)esponding section r °dONLNdÆØ‘ªÊ)VecorÛİdONLNd≤ØÊª )ds and alias rå °dONLNd¿Ø!ª3);ecorİdONLNdƒØ4ª@)ds.ˇ(ö@ˇ ˇˇˇˇ@
  10359. ˇ·ˇ‚7^
  10360. 4H\, Palatino
  10361. .+ä"CHAPTER €`)\1,     Helvetica
  10362.     (@äThe Edition Manager4⁄ä˙(‡äUsing ◊P)The Edition Manager
  10363. ~¿(‡1
  10364. ‡)-a¿)16
  10365. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿
  10366. .°dONLNd\ähû(eäThe ,
  10367. Courier°dONLNd\ûhÏ)
  10368. SectionRecord°dONLNd\Ïh/)N data type defi°dONLNd \/hv)Cnes the section rR`°dONLNd1\vhà)Gecor$¿°dONLNd5\àhì)d. Δ`°dONLNd8\íhö)
  10369. A9¿°dONLNd9\öh¡)
  10370.  section r  °dONLNdC\¡h”)'ecorfiİdONLNdG\“h) d contains .°dONLNdRhät(qäZinformation to identify the data contained within a section as a publisher or a subscriberİdONLNd¨ht(q, °dONLNdÆtäÄ‘(}äa time stamp to r¿°dONLNdøt’ÄÁ)Kecorè °dONLNd√tÁÄ/)d the last modifi `°dONLNd‘t/ć)H)cation of the section, and unique identifi™°dONLNd˛t·Ä
  10371. )≤ cation for °dONLNd    Ääå¡(âä
  10372. each section.
  10373. ØH¿4∞H¿"∞H_
  10374. ˇ·ˇ‚7^
  10375.     °dONLNdˇˇ*$
  10376. Figure 1-9°dONLNd•Ã∞“)BA0°dONLNd•“∞Œ)? document with a publisher and subscriber and its resource fork
  10377. øH4¿H
  10378. ¬w4¿v¬wò2çç¬wÆœ˚˜ˇı˜ˇ˜˚˜ˇÄˆ˜ˇÄ¯˚˜ˇ¿ˆ˜ˇ¿¯˚˜ˇ‡ˆ˜ˇ‡¯˚˜ˇˆ˜ˇ¯˚˜ˇ¯ˆ˜ˇ¯¯˚˜ˇ¸ˆ˜ˇ¸¯˚˜ˇ˛ˆ˜ˇ˛¯˚ˆˇˆˆˇ¯˚ˆˇÄ˜ˆˇÄ˘˚ˆˇ¿˜ˆˇ¿˘˚ˆˇ‡˜ˆˇ‡˘˚ˆˇ˜ˆˇ˘˚ˆˇ¯˜ˆˇ¯˘˚ˆˇ¸˜ˆˇ¸˘˚ˆˇ˛˜ˆˇ˛˘˚ıˇ˜ıˇ˘˚ıˇÄ¯ıˇÄ˙˚ıˇ¿¯ıˇ¿˙˚ıˇ¿¯ıˇ‡˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ
  10379. ¿ˇˇ˛†ıˇ˙˚ıˇ¿˛ˇ‡ıˇ˙˚ıˇ¿˛ˇ‡ıˇ˙˚Ùˇ
  10380. ¿ćıˇ˙¸üıˇ
  10381. ¿øÛ¿‡ıˇ˙¸ıˇ
  10382. ¿ø˜‡‡ıˇ˙¸ıˇ
  10383. ¿øÓp‡ıˇ˙8Aıˇ
  10384. ¿øÏ0‡ıˇ˙$ÚˇÉøÏ?‡Úˇ‡Ä@ˇ%=MìÚˇ√øÓ‡ÚˇÄ@ˇ93_>ÇÚˇ„æ„‡Úˇ…„7s0!3[0ûÚˇÛæ√√‡Úˇ©óÕO† ˝M.ÇÚˇ„Ň√‡Òˇ‚)ñ≈L ¸Úˇ√É√‡Úˇ«„=s†¸ÚˇÉá8ˇ‡Úˇ˙¸ıˇ
  10385. ¿éˇ‡ıˇ˙¸ıˇ
  10386. ¿ü˛‡ıˇ˙¸ıˇ
  10387. ¿ü˛‡ıˇ˙¸Ùˇ
  10388. ¿ćıˇ˙˚ıˇ¿˛ˇ‡ıˇ˙˚ıˇ¿˛ˇ‡ıˇ˙˚ıˇ¿˛ˇ†ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ
  10389. ¿Çıˇ˙˚ıˇ
  10390. ¿ıˇ˙˚ıˇ
  10391. ¿:fflÄıˇ˙˚ıˇ
  10392. ¿éˇh¿ıˇ˙˚ıˇ
  10393. ¿∂ç´@ıˇ˙˚ıˇ
  10394. ¿vÌ¿ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙œœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœ%˝˛@p˛     @ÄÄÅ˝Ù%˝ ¿à    8Ä@Ä ˝000Ù$˝˝@àĆÄ˝Ù(˝"–˝ø@#Â(à@†}≥»ú„<<ù=‡x}ûs=gĈ'˝!q$îÄ@"%(àA"í)†îê    EãBê%ÑëÑìíı'˝!$ó¿N "…–àA"í(òó–ƒâBê%dëd˙ı'˝!ƒî@D"à    B"í(ÑîFâbê%ëQÇı(˝"9„˚¿‡¯˛úÉ<y›˘€˘Ω«ù⁄ v„Œ„ªé ˆ¸˝˝Ä ˝˝¯ ˆ¸0˝˛ ˝˝¯ ˆ ¸¿ˆp‚œ˝@  @‡ê@½¿¿!Ç Â˝@@Ç
  10395. 0½„ìÃ(Ü/9Áp«óGº
  10396. QˆxÈ˝î4R(…díHH≤»R
  10397. Qâ) È˝ì_À»$íHíHR    óây/†È˝êîpä»§ìH(“LR    âX» È˝fl;œùg~»ÓÌÁπ„ª:›≠ÁÈ Û˘Ë Û˘0ËͿ˜˝¿–¸fl˝@0˛Äfl˝Ä@˛Äfl˝ èæLΩümÿ Δ‡˝ DQRRH§§@    )‡˝ ƒQ_RH§æ@    (‡˝
  10398. $QP<RH§†@    (Ä·˝
  10399. wûÔ√ªo^‰∑ ·¸˝fi¸˝fi ¸8˝€œ˝
  10400. ¿¿¬·˝ @0ĉ˝ @
  10401. ĉ˝¬{ƒÚΔπ¿
  10402. {œx½c"&Câ$ë $§ê†Â˝/">OI"ë 
  10403. '‡ê†Â˝+"6KI#  ë2$"ò†Â˝≈ÒÀÂáù± ¥1¯á«s‹Gpˆ›ˆ›œœ
  10404. ˝ò˝¿`‹˝à  ê‹˝à a‹˝ãg'=‡¡‹˝â($2BÄ!‹˝â&$ÚBÄ!‹˝â!$≤bÇ`ê‹˝‹˛Y¡Ñ`‹œœœò2çç¬wÆœ˚˜ˇı˜ˇ˜˚¯Ĉ¯į˚¯¿ˆ¯¿¯˚¯`ˆ¯`¯˚¯0ˆ¯0¯˚¯ˆ¯¯˚¯ ˆ¯ ¯˚¯ˆ¯¯˚¯ˆ¯¯˚¯Ę¯Ģ˚¯¿˜¯¿˘˚¯`˜¯`˘˚¯0˜¯0˘˚¯˜¯˘˚¯ ˜v ¸ ˘˚¯˜)ùx¸˘˚¯˜)∞¸˘˚¯į&ïh¸Ä˙˚
  10405. q¿¯¯¿˙˚
  10406. 5np•π¿%Wˇˇ¿¯¯ˇˇ‡˙!˚
  10407. W’‡flWÄ+˛@¯~ja˚0˙#˚
  10408. )V`•YÄ%t@¯Iûë∫U’Ä˝0˙˚ı@¯~û∑oظ0˙˚ı@¯JnùÛG≠¸0˙˚
  10409.  GÄ~<%$Ã@¯ı0˙˚
  10410. UÃÄ> dzÍX@¯ı0˙˚
  10411. _À9¥XwÊÑ@¯ı0˙˚
  10412. NUT®/-ò@¯ı0˙˚ı@¯ı0˙˚ı@¯ı0˙˚
  10413. NlÄN$%$x@¯ı0˙˚
  10414. ∂≈@=∂\z‹»@¯ı0˙$˚
  10415. ¸)¿:¸|¸∞@¯
  10416. PÄ 0˙$˚
  10417. LÿÄL§'%P@¯
  10418. R·“–™MfiNP0˙˚ı@¯
  10419. wÛ∫πˇÓflÌ0˙˚ı@¯
  10420. R°í∞∫M∫Mp0˙˚
  10421. KeÄk$'4H@¯˚¸0˙˚
  10422. ∂ Ä=÷Zj¥@¯ı0˙ ˚
  10423. }Ø?≠zs^t@¯˝ Ä˚0˙!˚
  10424. ŒU^§-%»@¯UZÍeÄ˚0˙˚ı@¯[WoÓÄ˚0˙˚ı@¯$“⁄e¿˚0˙˚
  10425. nLÄO$-$»@¯@@˘0˙˚
  10426. ›•@>fiZwZX@¯ı0˙˚
  10427. 7©¿9’>{vX@¯ı0˙!˚ŒXÄN‰)-H@ˇˇ˛†ı0˙˚ı@˛ˇ‡ı0˙˚ˆD@@˛ˇ‡˜U@0˙˚¯Ä˜ Ä@ć ˜Ã¿0˙$¸ò˛8ĉ @øÛ¿‡˜$0˙+¸%µZ"⁄¥L®@ø˜‡‡  ÑG∞˙+¸%Ì˙?ªÙU¸@øÓp‡ %’–[VÄ    ï ∞˙.*8AÎt"÷ËLË@øÏ0‡o_P˜~Ä
  10428. øÄ@∞˙2    $@˛˝_ˇˇ˝ÉøÏ?‡ˇˇ˚Gw Z›    ù@∞‡Ä@ˇ+%=MìĘò˛à√øÓ‡ààâà@˝@∞Ä@ˇ,93_>Ç D¿J$%<L˛c愇Ė˜ ∞…„7s03!3[0ûUÕÄ:µZz‰ÿ˛æ√√‡Äp,≤,…DÄßâ¿∞©óÕO†3 ˝M.Ç^Õ@:6ƒ˛"cŇ√‡¢""–uUxV´@\õ ˇ‚)ñ≈L 0¸
  10429. OTÄ Ï'ÂX˛√É√‡Äàu“tOÊ¿‚ò¿∞«„=s†$¸@˜_ˇˇ˝Éá8ˇ‡ˇˇ˚$ó(Y]ĸ´@∞˙¸Ę Ä@顇˜@∞˙$¸NF¿N$%&l@ü˛‡ ˜ ∞˙+¸%∂≠Ä=⁄Z{\ÿ@ü˛‡$≤<IƒÄ§Õ¿∞˙+¸%¯^„@:ƒv"¥@ć{UxªK@kõ ∞˙*˚Í\Ä\¨%}H@˛ˇ‡u◊X鿉V¿∞˙"˚ˆD@@˛ˇ‡.ìhÎïÄØ©A∞˙˚ˆàÄ@˛ˇ† ˜Ã«0˙˚
  10430. NEÄO$'4H@¯˜3 0˙˚
  10431. ÷™Ä=æZj¥@¯ı0˙˚
  10432. fiO?EVs^¥@¯ı0˙!˚Jı˛¨-%H@Çı0˙˚ı
  10433. @ı0˙!˚ı@:fflÄx†¿Ä˛0˙*˚$NGÄo$-<H@éˇh¿,î≠“vT‰ÁIH’∞˙*˚$Ω¨Ä>fiZv‰¥@∂ç´@+˛µø~Ïfi⁄ˇ˝_0˙*˚$Á´9•~{‘\@vÌ¿*îØíVT‘÷MH•0˙˚
  10434. ^U^§)%Ë@¯˛˘0˙˚ı@¯ı0˙˚ı@¯
  10435. ¿ë0 ∞˙$˚
  10436. JDÄk&'$ÿ@¯
  10437. &”V„]5’ñË≤i∞˙$˚
  10438. µ´@>÷lZH@¯
  10439. u™≠“ˆ”ªM›˜æ∞˙$˚
  10440. ˇØ¿==bs~à@¯
  10441. 5íµ”U3µL»Úi∞˙˚
  10442. NTÄ ¨-%à@¯˝˙0˙˚ı@¯˝˙0˙$˚
  10443.  GÄn<-§Ã@¯
  10444. @¿Ä `0˙$˚
  10445. UÃÄ>⁄dwZX@¯
  10446. j‰ÁID®•ómÄ0˙$˚
  10447. ^À>4XzˆÑ@¯
  10448. Zfi⁄ˇÎykÍÄ0˙$˚
  10449. OUî)-ò@¯
  10450. d‘÷MD®•ïÎÄ0˙˚ı@¯¸0˙˚ı@¯˙˝0˙#˚
  10451. NLÄK$%&x@¯˝ÅÇÇFÄ0˙$˚
  10452. ∂•@=æ\{\»@¯
  10453. +,§≠ k¶Ø[V†0˙$˚
  10454. ^È¿:˘|"∞@¯
  10455. v˚˛Ÿæ^⁄WzΩ0˙$˚
  10456. ÍXÄN§%}P@¯
  10457. +*§©Æj߯⁄µ†0˙˚ı@¯˝@˛0˙˚ı@¯˝@¸0˙$˚
  10458. NEÄK$'4H@¯
  10459. BÄ ‰ D0˙$˚
  10460. ÷™Ä=÷Zj¥@¯
  10461. R L›+ÊEmdŒ_p˙$˚
  10462. fiO?…zs^t@¯
  10463. jøÌ[ˆÂÔ}Ô]∑p˙$˚
  10464. Jı^§-%»@¯
  10465. R™L˘&ÊDªdÕV∞˙˚ı@¯˛Ä˚0˙˚ı@¯ı0˙˚
  10466. NDÄO$-6H@¯ı0˙˚
  10467. Ω´@>fiZvÏ¥@¯ı0˙˚
  10468. Á´@9’>{“t@¯ı0˙˚
  10469. ^TÄN‰)-»@¯ı0˙˚ı@¯ı0˙˚ı@¯ı0˙˚ı@¯ı0˙˚ı@¯ı0˙˚ı@¯ı0˙˚ı@¯ı0˙˚ıˇ¿¯ıˇ˙˚ıˇ¿¯ıˇ˙œœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœœ%˝˛@p˛     @ÄÄÅ˝Ù%˝ ¿à    8Ä@Ä ˝000Ù$˝˝@àĆÄ˝Ù(˝"–˝ø@#Â(à@†}≥»ú„<<ù=‡x}ûs=gĈ'˝!q$îÄ@"%(àA"í)†îê    EãBê%ÑëÑìíı'˝!$ó¿N "…–àA"í(òó–ƒâBê%dëd˙ı'˝!ƒî@D"à    B"í(ÑîFâbê%ëQÇı(˝"9„˚¿‡¯˛úÉ<y›˘€˘Ω«ù⁄ v„Œ„ªé ˆ¸˝˝Ä ˝˝¯ ˆ¸0˝˛ ˝˝¯ ˆ ¸¿ˆp‚œ˝@  @‡ê@½¿¿!Ç Â˝@@Ç
  10470. 0½„ìÃ(Ü/9Áp«óGº
  10471. QˆxÈ˝î4R(…díHH≤»R
  10472. Qâ) È˝ì_À»$íHíHR    óây/†È˝êîpä»§ìH(“LR    âX» È˝fl;œùg~»ÓÌÁπ„ª:›≠ÁÈ Û˘Ë Û˘0ËͿ˜˝¿–¸fl˝@0˛Äfl˝Ä@˛Äfl˝ èæLΩümÿ Δ‡˝ DQRRH§§@    )‡˝ ƒQ_RH§æ@    (‡˝
  10473. $QP<RH§†@    (Ä·˝
  10474. wûÔ√ªo^‰∑ ·¸˝fi¸˝fi ¸8˝€œ˝
  10475. ¿¿¬·˝ @0ĉ˝ @
  10476. ĉ˝¬{ƒÚΔπ¿
  10477. {œx½c"&Câ$ë $§ê†Â˝/">OI"ë 
  10478. '‡ê†Â˝+"6KI#  ë2$"ò†Â˝≈ÒÀÂáù± ¥1¯á«s‹Gpˆ›ˆ›œœ
  10479. ˝ò˝¿`‹˝à  ê‹˝à a‹˝ãg'=‡¡‹˝â($2BÄ!‹˝â&$ÚBÄ!‹˝â!$≤bÇ`ê‹˝‹˛Y¡Ñ`‹œœœˇ†@ˇ ˇˇˇˇ@
  10480. ˇ·ˇ‚7^
  10481. 4*\˜, Palatino
  10482. .+l"CHAPTER €`)\1,     Helvetica
  10483.     (@lThe Edition Manager4⁄*˙¯
  10484. (‡*1 )-c)17
  10485.     )9Using ◊P)The Edition Manager
  10486. (ÔlDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯,
  10487. Courier
  10488. .°dONLNd\lhÍ(elTYPE SectionRecord = °dONLNdj~v¢+RECORD°dONLNd xêÑ¿+version:°dONLNd-xÍÑ,)Z SignedByte;°dONLNd=xDÑ™)Z{always 1 in 7.0}°dONLNdQÜêíÆ(èêkind:°dONLNd[ÜÍí2)Z SectionType;°dONLNdlÜDí⁄)Z{publisher or subscriber}°dONLNdàîê†Æ(ùêmode:°dONLNdíî͆,)Z UpdateMode;°dONLNd¢îD†¬)Z{automatic or manual}°dONLNd∫¢êÆ∫(´êmdDate:°dONLNdΔ¢ÍÆ&)Z
  10489. TimeStamp;°dONLNd’¢DÆ⁄)Z{last change in document}°dONLNdÒ∞êºÃ(πê
  10490. sectionID:°dONLNd∞ͺ)ZLongInt;°dONLNd
  10491. ∞Dº‘)Z{application-specific, }°dONLNd2æD »*{ unique per document}°dONLNdKÃêÿ∫(’êrefCon:°dONLNdWÃÍÿ)ZLongInt;°dONLNddÃDÿ»)Z{application-specific}°dONLNd}⁄êÊ¥(„êalias:°dONLNdà⁄ÍÊ2)Z AliasHandle;°dONLNdô⁄DÊ‘)Z{handle to alias record}°dONLNdµˆêÊ(ˇê9{The following fields are private and are set up by the }°dONLNdÒê‡*8{ RegisterSection function described later within this }°dONLNd,êû*-{ chapter. Do not modify the private fields.}°dONLNd].ê:¿*subPart:°dONLNdj.Í:)ZLongInt;°dONLNdw.D:z)Z    {private}°dONLNdÉ<êHÿ(Eê nextSection:°dONLNdî<ÍH>)ZSectionHandle;°dONLNdß<DHÊ)Z{private, do not use as a }°dONLNdœJDVò*{ linked list}°dONLNd‡Xêdfi(aê
  10492. controlBlock:°dONLNdÚXÍd)ZHandle;°dONLNd˛XDdÚ)Z{may be used for comparison }°dONLNd(fDrn*{ only}°dONLNd2têÄ∫(}êrefNum:°dONLNd>tÍÄ>)ZEditionRefNum;°dONLNdQtDÄz)Z    {private}°dONLNd[ÇléÑ(ãlEND;
  10493. ù*≠¯4û*¨¯
  10494.     .°dONLNdˇˇ*Field descriptions
  10495. ˇ·ˇ‚7^
  10496. °dONLNd`™l∂å*version°dONLNdh™»∂g)\&Indicates the version of the section rm†°dONLNdé™g∂y)üecor‚°dONLNdí™y∂ñ)d, curr,¿°dONLNdô™ó∂√) ently $01. °dONLNd•πl≈Ä(¬lkind°dONLNd™π»≈⁄)\Defi†°dONLNdÆπ€≈Î)@nes the section type as either publisher or subscriber with the °dONLNdÓ≈»—j(Œ»&stPublisher or stSubscriber constant. °dONLNd‘l‡Ö(›lmode°dONLNd‘»‡*)\Indicates if editions arj‡°dONLNd2‘*‡Œ)b#e updated automatically or manuallyg‡°dONLNdU‘Õ‡“)£. °dONLNdX„lÔè(ÏlmdDate°dONLNd_„»ÔT)\Indicates which version (modifiº†°dONLNd~„TÔˆ)å'cation date) of the section’s contents °dONLNd•Ô»˚ï(¯»/is contained within the publisher or subscriberó °dONLNd‘Ôï˚˜)Õ. The mdDate is set to °dONLNdÎ˚»(»
  10497. 0 when you cr`°dONLNd¯˚Ê)?5eate a new subscriber section, and is set to the currÏ °dONLNd-˚Âı)fient °dONLNd1»(»time when you crÿ°dONLNdAp)Meate a new publisherÉ@°dONLNdUpê)[. Be surÒ¿°dONLNd]ê‹) e to update this fiÍ °dONLNdp›Ì)Meld °dONLNdt»^(»!each time publisher data is modifi›¿°dONLNdñ^Δ)ñed. The section’s modifiΔ°dONLNdÆ«‰)ication °dONLNdµ»+((»date is comparN°dONLNd√    +x)Aed to the edition’s modifif†°dONLNd›x+Â)ocation date to determine °dONLNdˆ+»7fl(4»?whether the section and the edition contain the same data. The °dONLNd57»C*
  10498. section modifiB‡°dONLNdC7CÕ)?.cation date is displayed in the publisher and °dONLNdqC»Oi(L»%subscriber options dialog boxes. See .†°dONLNdñCjOΔ)¢“Closing an Edition”å@°dONLNd™CΔOÍ)\
  10499.  later in °dONLNd¥O»[m(X»'this chapter for detailed information. °dONLNd‹^ljñ(gl    sectionID°dONLNdÊ^»j—)\PrN†°dONLNdË^“j‡)
  10500. ;ovides a unique number for each section within a document. (İdONLNd#^‡jÁ(g‡Ac °dONLNd$^ÁjÈ) °dONLNd%j»vk(s»%simple way to implement this is to crπ°dONLNdJjkv–)£eate a counter for each °dONLNdbv»Ç·(»>document that is saved to disk with the document. The counter °dONLNd†Ç»ér* )should start at 1. The section ID is currö@°dONLNd…ÇréÃ)™ently used as a tie br†°dONLNdflÇÕéÚ)[    eaker in °dONLNdËé»öÎ(ó»the GoT)¿°dONLNdÔéÎöq)#oPublisher function when ther«°dONLNd éqöÅ)Üe ar’†°dONLNdéÅöÏ)e multiple publishers to °dONLNd)ö»¶ı(£»Dthe same edition in a single document. The section ID should not be °dONLNdm¶»≤˚*
  10501. 0 or –1. See ; °dONLNdz¶¸≤¥)4(“Duplicating Publishers and Subscribers”É`°dONLNd¢¶¥≤Í)∏ later in this °dONLNd±≤»æõ(ª»0chapter for information on multiple publishers. ˇ@ˇ ˇˇˇˇ@
  10502. ˇ·ˇ‚7^
  10503. 4H\, Palatino
  10504. .+ä"CHAPTER €`)\1,     Helvetica
  10505.     (@äThe Edition Manager4⁄ä˙(‡äUsing ◊P)The Edition Manager
  10506. ~¿(‡1
  10507. ‡)-a¿)18
  10508. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿
  10509. °dONLNd\ähç(eärE°dONLNd\éh®)efCon°dONLNd\Êh˝)XRefer⁄ °dONLNd \˝hΔ).ence constant available for application-specififi¿°dONLNd;\Δh‡)…c use. °dONLNdCkäwû(täalias°dONLNdIkÊwn)\ Contains a handle to the alias rÔİdONLNdiknwÄ)àecorc‡°dONLNdmkÅw)"d for a particular section within °dONLNdèwÊÉ(ÄÊ a document. .°dONLNdúõäßÍ(§äWhenever the user crR`°dONLNd∞õÍßq)`eates a publisher or subscriberï°dONLNdœõpßõ)Ü , call the ,
  10510. Courierï°dONLNd⁄õõß◊)+
  10511. NewSectionï°dONLNd‰õ◊ß
  10512. )<
  10513.  function to .°dONLNdÒßä≥í(∞äcrµ@°dONLNdÛßí≥‹)eate the section rï¿°dONLNdß‹≥Ó)Jecor
  10514.  °dONLNd    ßÔ≥5)d and the alias r√ °dONLNdß5≥G)Fecor7İdONLNdßH≥P)d..°dONLNd!øäÀ
  10515. (»ä@err := NewSection (container, sectionDocument, kind, sectionID, °dONLNdgÕ‰Ÿˆ+Z   °dONLNdkÕˆŸÜ) initialMode, sectionH);°dONLNdÑÂäÒû(ÓäThe °dONLNdàÂûÒ⁄)
  10516. NewSection°dONLNdíÂ⁄Ò
  10517. )<  function crR`°dONLNdûÂ
  10518. Òe)0eates a new section r$¿°dONLNd≥ÂeÒw)[ecor˜ °dONLNd∑ÂvÒ)$d (either publisher or subscriber), .°dONLNd€Òä˝
  10519. (˙äindicates whether editions arzİdONLNd¯Ò
  10520. ˝Æ)Ä#e updated automatically or manuallywİdONLNdÒ≠˝Ú)£, sets the modifi5@°dONLNd,ÒÛ˝)Fcation °dONLNd3˝ä    Ω(ä date, and crJ °dONLNd?˝æ    ˛)4eates an alias rć°dONLNdO˝˛    )@ecorı@°dONLNdS˝    )d fr©‡°dONLNdW˝     )6om the document containing the section to the edition °dONLNdç    ä≥(ä    container2 °dONLNdñ    ≥∏)). .°dONLNdôä'û($äThe °dONLNdùû'¯)sectionDocument°dONLNd¨¯'\)Z parameter can be NIL!†°dONLNd¡\'è)d
  10521.  if your currÙ°dONLNdŒé')2ent document has never been °dONLNdÍ'ä3œ(0äsaved. Use the °dONLNd˘'œ3/)EAssociateSection°dONLNd    '/3¥)` function to update the alias rR`°dONLNd('¥3Δ)Öecor$¿°dONLNd,'Δ3Â)d of a r˜ °dONLNd4'‰3)egister…İdONLNd;'3)ed .°dONLNd>3ä?(<ä section when the user names or r‚¿°dONLNd^3?ƒ)ë#enames a document by choosing Save ,‡°dONLNdÅ3≈?⁄)™As fr °dONLNdÜ3⁄?
  10522. ) om the File .°dONLNdí?äKÃ(Hämenu. If you arR`°dONLNd°?ÃK€)Be cr$¿°dONLNd•?€K[)eating a subscriber with the $¿°dONLNd¬?[Kù)Ä initialMode$¿°dONLNdÕ?ùKÔ)B parameter set to r˜ °dONLNd‡?ÓK
  10523. )Qeceive .°dONLNdÁKäW(Tänew editions automatically`İdONLNdKWU)w, your application r⁄¿°dONLNdKUW    )T)eceives a Section Read event each time a °dONLNd>Wäcc(`ä1new edition becomes available for this subscriberC@°dONLNdoWcce)Ÿ..°dONLNdqiäuÆ(rä    If an errR`°dONLNdziÆuÌ)$or is encounter$¿°dONLNdâiÌu)?ed, the $¿°dONLNdëiu?)"sectionH$¿°dONLNdôi?uÃ)0" parameter is set to NIL. If not, $¿°dONLNdªiÃu¸)çsectionH$¿°dONLNd√i¸u˛)0 .°dONLNdƒuäÅN(~ä.contains the handle to the allocated section r_ °dONLNdÚuNÅ`)ƒecor”İdONLNdˆu`Åh)d..°dONLNd˘áäì≠(êäSet the °dONLNdá≠ìÔ)# initialMode°dONLNd áÔì)B@ parameter to the update mode for each subscriber and publisher .°dONLNdLìäüí(úäcrµ@°dONLNdNìíüÆ)eated. y°dONLNdUìØüµ)Y9İdONLNdVìµüß)6ou can specify the update mode using these constants: .°dONLNdç´ä∑®(¥äCONST°dONLNdï´¿∑)6 sumAutomatic°dONLNd¶´∑2)Z= 0;°dONLNd≠´P∑Ï)6{subscriber receives new }°dONLNdŸπP≈Ê*{ editions automatically}°dONLNdˆ«¿”ˆ(–¿    sumManual°dONLNd«”2)Z= 1;°dONLNd «P”Ï)6{subscriber receives new }°dONLNd1’P·»*{ editions manually}°dONLNdI„¿Ôˆ(Ï¿    pumOnSave°dONLNdW„Ô2)Z= 0;°dONLNd^„PÔ‘)6{publisher sends new }°dONLNdÄÒP˝¬*{ editions on save}°dONLNdòˇ¿ ˆ(¿    pumManual°dONLNd¶ˇ 2)Z= 1;°dONLNd≠ˇP Ï)6{publisher does not send }°dONLNd”
  10524. PÚ*{ new editions until user }°dONLNdˆ'($ °dONLNd˚P'å)H
  10525. { request}.°dONLNd3ä?õ(<äSee ”°dONLNd
  10526. 3õ?V)(“Using Publisher and Subscriber Options”h@°dONLNd23W?Á)º$ later in this chapter for detailed °dONLNdV?äKñ(Hä:information on update modes for publishers and subscribersÜ`°dONLNdê?ñKõ(Hñ. 
  10527. pHv4qHv qäq
  10528. ˇ·ˇ‚7^
  10529. ˇˇ◊ˇ◊°dONLNdì_äpü(lä%Saving a Document Containing Sectionsˇˇˇˇˇˇ®(l1
  10530. °dONLNdπväǯ(äQWhen saving a document that contains sections, you should write out each section °dONLNd
  10531. Çäéç* rE°dONLNd Çéé†)ecorπ`°dONLNddžéø)d as a rW °dONLNdÇ¿éÿ) esourü`°dONLNdÇÿéã),ce of type 'sect' and write out each alias ri°dONLNdHÇåéû)¥ecor›`°dONLNdLÇûéΩ)d as a r{ °dONLNdTÇæé÷) esour√`°dONLNdYÇ÷é) ce of type °dONLNddéäö/(óä('alis' with the same ID as the section r§@°dONLNdåé/öA)•ecor†°dONLNdêéBöç)d. See the Resour€°dONLNd°éçöˆ)Kce Manager chapters in °dONLNd∏öä¶ë(£äVú`°dONLNdπöê¶})5olume I and this volume for detailed information on r≠¿°dONLNdÓö}¶ï)Ìesourˆ°dONLNdÛöï¶ß)ces. ˇ(@ˇ ˇˇˇˇ@
  10532. ˇ·ˇ‚7^
  10533. 4*\˜, Palatino
  10534. .+l"CHAPTER €`)\1,     Helvetica
  10535.     (@lThe Edition Manager4⁄*˙¯
  10536. (‡*1 )-c)19
  10537.     )9Using ◊P)The Edition Manager
  10538. (ÔlDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯
  10539. °dONLNd\lhG(el2If a user closes a document that contains newly crc†°dONLNd2\Ghˆ)€'eated publishers without attempting to °dONLNdYhlt¬(qlOsave its contents, you should display an alert box similar to the one shown in §¿°dONLNd®h¬t⁄(q¬FigurwİdONLNd≠h⁄t·)e °dONLNdØtlÄ~(}l1-10”‡°dONLNd≥t~ÄÉ). 
  10540. £*¥¯4§*¥¯"§*_
  10541. ˇ·ˇ‚7^
  10542.     °dONLNdˇˇ(°l Figure 1-10°dONLNd∂ôƧ)BThe new publisher alert box
  10543. °dONLNd“;lG÷(DlIf you keep the section rmİdONLNdÎ;÷GË)jecor·‡°dONLNdÔ;ËG")ds and alias rzİdONLNd˝;#G5);ecorÓ‡°dONLNd;5G„)(ds for each publisher and subscriber as .°dONLNd)GlSp(PlrR`°dONLNd*GpSá)esour$¿°dONLNd/GáSfi)ces, you can use the ,
  10544. Courier$¿°dONLNdDGfiS8)WChangedResource$¿°dONLNdSG8SE)Z or $¿°dONLNdWGESì)
  10545.  
  10546. WriteResource$¿°dONLNddGìS⁄)N function. If you .°dONLNdvSl_¡(\ldetach the section rÙ@°dONLNdäS¡_”)Uecorh†°dONLNdéS‘_)ds and alias r@°dONLNdúS_!);ecoru†°dONLNd†S!_5)ds frg@°dONLNd•S5_·)'om each section, you need to clone the .°dONLNdÃ_lk»(hlhandles and use the °dONLNd‡_»k
  10547. )\ AddResource°dONLNdÎ_
  10548. kw)B function. See the ResourR`°dONLNd_wk›)mce Manager chapter in °dONLNdklwt(tlVd@°dONLNdksw))(olume V for detailed information on the d@°dONLNdCk)wÉ)∂ChangedResourced@°dONLNdRkÉwà)Z, d@°dONLNdTkàw÷)
  10549. WriteResourced@°dONLNdak÷wÓ)N, and °dONLNdgwlÉÆ(Äl AddResource°dONLNdrwÆÉ€)B  functions.°dONLNd~âlïë(ílUse the °dONLNdÜâëïÎ)%PBExchangeFiles°dONLNdïâÎï5)Z function to ensurR`°dONLNdßâ5ïˆ)J*e that each time you save a document that .°dONLNd—ïl°—(ûlcontains sections, the fi‡°dONLNdÍï“°Ì)fle ID r†°dONLNdÒïÓ°j)emains the same. Saving a fiö†°dONLNd
  10550. ïj°Õ)|le typically involves cr¯¿°dONLNd%ïÕ°Ú)c    eating a °dONLNd.°l≠á(™lnew fi˛¿°dONLNd4°á≠‚)Rle (with a temporary name), writing data to it, closing it, and then deleting the °dONLNdÜ≠lπó(∂l
  10551. original fiéİdONLNdë≠óπ—)+le that you arÁ`°dONLNdü≠—π‹):e rˆ°dONLNd¢≠‹π)
  10552. eplacing. 5†°dONLNd¨≠π
  10553. )+Yˆ °dONLNd≠≠ π)ou r∑¿°dONLNd±≠πÖ)ename the temporary fi&İdONLNd«≠Üπ‹)hle with the original .°dONLNd‹πl≈s(¬lfi°dONLNdfiπs≈)lename, which leads to a new fi°dONLNd˝π≈2)è le ID. The °dONLNdπ2≈å)0PBExchangeFiles°dONLNdπå≈‰)Z function swaps the .°dONLNd+≈l—»(Œlcontents of the two fiV@°dONLNdA≈…—)]les (even if they ar¿°dONLNdU≈—ÿ)Q,e open) by getting both catalog entries and °dONLNdÅ—l›!(⁄l*swapping the allocation pointers. If the fi °dONLNd¨—!›8)µles ar$ °dONLNd≤—9›q)
  10554. e open, the fiÍİdONLNd¿—q›í)8le contr€°dONLNd»—훋)!ol block (FCB) is °dONLNd⁄›lÈ»(Êlupdated so that the rw¿°dONLNdÔ›»Èÿ)\efer#‡°dONLNdÛ›ŸÈÿ)9ence numbers still access the same contents (under a new °dONLNd,Èlı‹(ÚlSname). See the File Manager chapter in this volume for detailed information on the .°dONLNdılΔ* PBExchangeFiles°dONLNdéıΔÔ)Z
  10555.  function..°dONLNdôlö(l Listing 1-2 @°dONLNd§õ)/ illustrates how to save a fi™‡°dONLNd¡})ule that contains sections. Í`°dONLNd‹}’)mAs described earlierU °dONLNd’Ì)X, you °dONLNdˆl(l'should write out the eligible section r‚İdONLNd")§ecorV‡°dONLNd!#])ds and alias rÔİdONLNd/]o):ecorc‡°dONLNd3på)ds as r憰dONLNd:å§)esour‡°dONLNd?•Í)ces to allow for °dONLNdPl+Ç((lfuturÈİdONLNdUÇ+ƒ)e compatibility@°dONLNddƒ+›)B. Therë°dONLNdj›+Ì)e arü†°dONLNdnÌ+")
  10556. e several dif °dONLNd{"+.)5fer«†°dONLNd~.+Õ) $ent techniques for saving or adding °dONLNd¢+l7o(4lrE°dONLNd£+p7à)esourç@°dONLNd®+à7ü)Cces; this listing illustrates one technique. The section handles arj°dONLNdÎ+ü7Ë(4üe still valid after .°dONLNdˇ7lCó(@l
  10557. using the °dONLNd    7óCŸ)+ AddResource°dONLNd7ŸCÙ)BE function because this listing illustrates just saving, not closing, .°dONLNdYClOÇ(Llthe fiÍ °dONLNd_CÇOå)le.°dONLNdcUlaÉ(^lBeforÛ¿°dONLNdhUÉa∏)He you write out sections, you need to see if any publisher sections shar¡¿°dONLNd∞UπaÍ(^π e the same °dONLNdªalmÇ(jlcontr>İdONLNd¿aÉm)ol block. Publishers that sharõİdONLNdfiamI)e the same contr[†°dONLNdÓaJmÇ)H
  10558. ol block sharq¿°dONLNd˚aÇm‘)8e the same edition.°dONLNdslö(|l If a user cr˰dONLNdsö).eates an identical copy of a fi;†°dONLNd:ss)Äle by choosing Save  °dONLNdNssà)YAs fr•@°dONLNdSsàÎ)om the File menu and .°dONLNdhlã!(àl'does not make any changes to this new fi°dONLNdê!ãÖ)µle, you simply use the °dONLNdßÖãÂ)dAssociateSection°dONLNd∑ÂãÁ)` .°dONLNd∏ãló›(îlTfunction to indicate to the Edition Manager which document a section is located in. 
  10559. ≥l#¯4¥l#¯†Ç
  10560. ≥l#√ò6"0Àÿ"1À“µm#|ÀÀŒˇœœœˇ˘œˇ˘œœœœœœœœœœœœœ ˝‘
  10561. ˝Ä’
  10562. ˝Ä’.˝ ¿˛˚`˚`˛0ĸ‡0˝0¸+˝ ¿˝c˛`˚`˛0˙0˝0¸5˝`˝$c„„√圯x¯<|xÒü·„333„1«√ΔŒ1„0˛3˝`˝c32ffL˝Ã`2ff1ôô˛3˝3&fg330˛4˝00˝c38ff ˝Ã`0ff0˘ôú˛3„˛3Üff„30˛5˝30˝$c3ff ÃøÃ`0ff1ôôé3Û3331ΔgÊ√30˛5˝gò˝$c3ff ÃÿÃ`0ff1ôôá33330Êf√30˛5˝gò˝$c3&ffLÃÃÃ`2ff1ôôì32332ff&0√30˛5˝«å˝$c3„√áÃÃxÃ0<f˘ôé1„¸Û„1ΔcΔ0¡·˛
  10563. ˝«å’˛áÜ’˛áÜ’˛É’˛É’˛ÅÄ÷˛ÅÄ÷&˛ Ä¿˚ ¸c`˚` ˝cˆ&˛ ¿˚ ¸c˛`˚` ˝cˆ2˛`˛ˇå«áå«ÄÛ„„√圯x¯<x «áèÄÛ·„˛˘/˛`˛˛Ã åHÃÿc32ffL˝Ã`Ã
  10564. åÃÿc˛3˘0˛00˛ÃÃŒ Ãÿc38ff ˝Ã`à Ãÿc˛3˘2˛00˛Ãë åÜ¿c3ff ÃøÃ`Üÿc3Û3˘2˛`IJÃÃ√å˛Ãc3ff ÃÿÃ`Ã˛ ¿c33˘3˛`IJ ÃÃ…åÃÃå@c3&ffLÃÃÃ`Ã
  10565. åLL¿c330˙3˛¿ ˛ Ã««áœÄ33„√áÃÃxÃ0 x «áèÄ31„30˙˛¿ ‰ Ùĉ Ù˛ˇ˛÷˛˛ˇ¸÷œœœœœœœœœœœœœœœœœ'˜p˝0¸Δ¸‡0˚0˚'˜»˝0¸Δ0Ä0˚0˚-˜!¿Òò>>èÁ√¿0„·áåœÒ·Δg¸<|x˚,˜·ôò3#˛32ÄΔf`1ôì1åÃΔ33&˝f0˚,˜p˘ôò3˛38ÄΔf`1ò˘É1åÃΔ33˝f0˚,˜9ôô¯˝3?ÄΔg‡1˘ôÉ1è«Ü33ff~f0˚,˜ôôÄ˝30ÄΔf1ÅôÉ1å Δ33ff`f0˚,˜ôôëà˝31&ÄΔf 1âôì1åLΔ33&ffbf0˚-˜!p˘‡33èfc¿0¯„1áå√Ò·√Êf<f˚ Ô‚ Ô#‚ Ô‚œœœœ!˜ HΔ1Äõ‡˛¿ÄÔ ˜ ê¿1ÄõIJ˝¿Ô!˜ŸôÒÊyèâ·„«çûΔ<8œá¿¿Ô!˜ŸôòΔ1ôôí31åŒ3&fdÃáÄÔ ˜ôòΔ1ôôÄ31åÃ3fpÃÃ√Ó ˜ôòΔ1üôÄ3ÒåÃ?f8ÃÃ√Ó ˜ôòΔ1òÄ3åÃ0fÃÿÓ ˜ôòΔ1òôÄ3åÃ1&fLÃÃ√Óˆ˘òfèÄ··áåΔ<8ë√Ó „¿Ó
  10566. ‰¿Ó
  10567. ‰ÄÓœœœœœœœœœœœœœœœœœœœœœœœœœ‹?¯ˇ
  10568. ‹˜ˇ¸›˜ˇ˛›‡¯¯¯ˇ˚˘ˇè¯ˇ«¯¯ ˚0˘¿∞¯7į¯˚ ˘@ ¯Ä¯ ¯˚@˘ @¯ į ¯˚@˘ @¯ Ä*¯ ¿8˛˚@<˝¿ @˚ Ä*¯ Ä¿d˛˚@b˝¿ @˚ Ä.¯
  10569.  è    ‡`xÃx˚@`<|8x¿ @3˛ Ä.¯
  10570.  ôôê¿påÃÃ˚@`Ffdÿ @#33˛ Ä.¯
  10571.  ôôÄ¿8|ÃÃ˚@`>f`ÿ @33˛ Ä.¯
  10572.  ôôÄ¿Ãø˚@`ff`¸¿ @33?˛ Ä.¯
  10573.  ôôÄ¿ Ãÿ˚@`ff`¿¿ @330˛ Ä.¯
  10574.  ôôÄ¿Lûƒ˚@bffdƒ¿ @321˛ Ä.¯
  10575.  Ä`8|x˚@<>f8x¿ @<˛ į ¯˚@˘ @¯ į ¯˚@˘ @¯ į ¯˚@˘ @¯ į¯˚ ˘@ ¯Ä¯¯ ˚0˘¿∞¯7ᝎ˚˘ˇè¯ˇ«›‡¯›˜ˇ˛
  10576. ‹˜ˇ¸‹?¯ˇœœœœœœœœœœœœˇ˘œˇ˘œœŒˇˇÀÀÀ†Éˇ
  10577. ˙@ˇ ˇˇˇˇ@
  10578. ˇ·ˇ‚7^
  10579. 4H\, Palatino
  10580. .+ä"CHAPTER €`)\1,     Helvetica
  10581.     (@äThe Edition Manager4⁄ä˙(‡äUsing ◊P)The Edition Manager
  10582. ~¿(‡1
  10583. ‡)-a¿)20
  10584. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿
  10585. gHj4gHj"gHa
  10586. ˇ·ˇ‚7^
  10587.     °dONLNdˇˇ(dä Listing 1-2°dONLNd\Œgj)D%Saving a document containing sections,
  10588. Courier
  10589. .°dONLNd&sHí(|H7PROCEDURE SaveDocument(thisDocument: MyDocumentInfoPtr;°dONLNdcÅ¢çÆ+Z  °dONLNdgÅΔçh)$numberOfSections: Integer);°dONLNdÑùH©Z(¶HVAR°dONLNdä´l∑®+$
  10590. aSectionH:°dONLNdö´ÿ∑,)lSectionHandle;°dONLNd´πl≈Δ(¬lcopiedSectionH:°dONLNd¿πÿ≈)lHandle;°dONLNd «l”∫(–l
  10591. copiedAliasH:°dONLNd›«ÿ”)lHandle;°dONLNdÁ’l·ê(filresID:°dONLNdÛ’ÿ·)lInteger;°dONLNd˛„lÔú(Ïlthisone:°dONLNd „ÿÔ)lInteger;°dONLNdˇH f(HBEGIN°dONLNd
  10592. l∂+$7{Write contents of publishers that need to be written }°dONLNdXl'¬*9{ during save. The GetSectionAliasPair function returns }°dONLNdî)l5‘*<{ a handle and resID to a section. The CheckForDataChanged }°dONLNd”7lCº*8{ function returns TRUE if the data in the section has }°dONLNdElQ¥* { changed. }°dONLNdSl_V*'FOR thisone := 1 TO numberOfSections DO°dONLNdGalmä*BEGIN°dONLNdPo~{¯+?aSectionH := GetSectionAliasPair(thisDocument, thisone, resID);°dONLNdì}~â\*%IF (aSectionH^^.kind = stPublisher) &°dONLNdΩãêóP+ (aSectionH^^.mode = pumOnSave) &°dONLNd‚ôê•P* (CheckForDataChanged(aSectionH))°dONLNdß~≥å(∞~-THEN DoWriteEdition(aSectionH, thisDocument);°dONLNd6µl¡®(æl
  10593. END; {for}°dONLNdCœl€⁄*={Set the curResFile to be the resource fork of thisDocument.}°dONLNdÉ›lÈ\*(UseResFile(thisDocument^.resForkRefNum);°dONLNd∞˘l∞*6{Write all section and alias records to the document.}°dONLNdÈlV*'FOR thisone := 1 TO numberOfSections DO°dONLNdl!ä*BEGIN°dONLNd#~/Œ+8{Given an index, get the next section handle and resID }°dONLNdX1~=º*5{ from your internal list of sections for this file.}°dONLNdë?~K¯*?aSectionH := GetSectionAliasPair(thisDocument, thisone, resID);°dONLNd‘M~Yû*0{Check for duplication of control block values.}°dONLNd[~gí*.CheckForDupes(thisDocument, numberOfSections);ˇ¶@ˇ ˇˇˇˇ@
  10594. ˇ·ˇ‚7^
  10595. 4*\˜, Palatino
  10596. .+l"CHAPTER €`)\1,     Helvetica
  10597.     (@lThe Edition Manager4⁄*˙¯
  10598. (‡*1 )-c)21
  10599.     )9Using ◊P)The Edition Manager
  10600. (ÔlDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯,
  10601. Courier
  10602. .°dONLNdj*vfi(s*{Save section record to disk.}°dONLNd"x`Ñ2+6#copiedSectionH := Handle(aSectionH)°dONLNdIÜ`í*HandToHand(copiedSectionH);°dONLNdhî`†û*5AddResource(copiedSectionH, rSectionType, resID, '');°dONLNd¢∞`º*{Save alias record to disk.}°dONLNd¬æ` \**copiedAliasH := Handle(aSectionH^^.alias);°dONLNdÃ`ÿˆ*HandToHand(copiedAliasH);°dONLNd
  10603. ⁄`Êí*3AddResource(copiedSectionH, rAliasType, resID, '');°dONLNdCËNÙä(ÒN
  10604. END; {for}°dONLNdQN *#  {Write rest of document to disk.}°dONLNdu*ú(*END; {SaveDocument}
  10605. E*K¯4F*K¯ FlF¯
  10606. ˇ·ˇ‚7^
  10607. ˇˇ◊.ˇ◊°dONLNdâ4lEÁ+B&2Opening and Closing a Document Containing Sectionsˇˇˇˇˇˇ®(A1
  10608. °dONLNdºKlWÿ(TlPWhen opening a document that contains sections, your application should use the .°dONLNd WlcÆ* GetResource°dONLNdWÆc()B function to get the section rR`°dONLNd5W(c:)zecor$¿°dONLNd9W:cÖ)d and the alias r˜ °dONLNdJWÑcñ)Jecor…İdONLNdNWñcÛ)d for each publisher ˇˇ¨°dONLNdcclo™(lland subscribern®°dONLNdqc™o—)>
  10609. . Set the ˇˇr¿°dONLNd{c—oÔ)'aliasˇˇ¨r¿°dONLNdÄcÔo˜) fi»°dONLNdÉc¯oI)    eld of the section r°H°dONLNdócIo[)Qecors®°dONLNdõc[o¯)%d to be the handle to the alias. See .°dONLNd¿ol{õ(xl
  10610. the Resour”†°dONLNd oõ{)/ce Manager chapter in V∏°dONLNd·o{µ)k(olume I for detailed information on the .°dONLNd    {láÆ(Ñl GetResource°dONLNd{ÆáŸ)B  function. °dONLNd çlôs(ñlYï°dONLNd!çrôπ)ou also need to rg`°dONLNd2çπô>)Gegister each section using the g`°dONLNdQç>ôò)ÖRegisterSectiong`°dONLNd`çòô◊)Z function. The °dONLNdoôl•Δ(¢lRegisterSection°dONLNd~ôΔ•—)Z= function informs the Edition Manager that a section exists. °dONLNdº±lΩ¯(∫lBerr := RegisterSection(sectionDocument, sectionH,aliasWasUpdated);ˇˇ—°dONLNdˇ…l’*The ˇˇs0Q°dONLNd…Ä’⁄)RegisterSectionˇˇ—Q°dONLNd…⁄’P)Z function adds the section r8¿°dONLNd.…P’b)vecor  °dONLNd2…b’“)d to the Edition Manager ¿°dONLNdJ…”’¯)q ’s list of .°dONLNdU’l·o(filrE°dONLNdV’p·ç)egisterî °dONLNd]’ç·h)3ed sections. This function assumes that the alias fiÓİdONLNdë’h·ø)€eld of each section r>`°dONLNd¶’¿·“)Xecor≤¿°dONLNd™’“·Î)d is a °dONLNd±·lÌ√(Ílhandle to the alias rXİdONLNdΔ·√Ì’)WecorǰdONLNd ·’Ì
  10611. )d. The alias rw °dONLNdÿ·Ì )9ecorÎİdONLNd‹· Ì=)d is a rq†°dONLNd‰·>ÌN)efer¿°dONLNdË·OÌ’) ence to the edition container frœ†°dONLNd·’̈)Üom the .°dONLNdÌl˘fl(ˆlsection’s document. If the °dONLNd*Ìfl˘9)sRegisterSection°dONLNd9Ì9˘Ô)Z+ function successfully locates the edition .°dONLNdd˘l?(l4container for a particular section, the section is r6 °dONLNdò˘@])‘egisterÖ@°dONLNdü˘]w)ed thr√`°dONLNd•˘w™) ough a shars‡°dONLNd∞˘´œ)4ed contró¿°dONLNd∏˘œˆ)$
  10612. ol block. °dONLNd¬lñ(l    The contrz@°dONLNdÀñÙ)*ol block is a private fi˛Ä°dONLNd„ÙE)^eld in the section r‡°dONLNd˜FX)RecorÖ@°dONLNd˚Xc)d. .°dONLNdˇl#à( lIf the °dONLNdà#‚)RegisterSection°dONLNd‚#0)Z function cannot fi°dONLNd(0#Ê)N*nd the edition container for a particular °dONLNdR#l/ò(,l
  10613. subscriber¬†°dONLNd\#ó/ú)+, ¬†°dONLNd^#ú/ˆ)RegisterSection¬†°dONLNdm#ˆ/¸)Z rï°dONLNdo#¸/+) eturns the ï°dONLNdz#+/£)/containerNotFoundWrnï°dONLNdé#£/©)x rg`°dONLNdê#©/ˆ)esult code. If the ˇˇ)P°dONLNd£/l;Δ(8lRegisterSectionˇˇ∏p°dONLNd≤/Δ;)Z function cannot fy–°dONLNdƒ/;Ù)J4ind the edition container for a particular publisher«Ä°dONLNd¯/Û;˜)„, ˇ˛1˰dONLNd˙;lGΔ(DlRegisterSectionˇˇe¯°dONLNd    ;ΔGœ)Z cr∏X°dONLNd ;œG˜)    Eeates an empty edition container for the publisher in the last place .°dONLNdQGlS“(PlOthe edition was located. The Edition Manager sends your application a Section Wô¿°dONLNd†G“S„(P“rite °dONLNd•Sl_Õ(\levent for that section. °dONLNdæelqÚ*VWhen a user attempts to open a document that contains multiple publishers to the same °dONLNdql}ç* Bedition, you should warn the user by displaying an alert box (see Ô†°dONLNdVqç}…(zç
  10614. “Duplicating °dONLNdc}lâË(ÜlPublishers and Subscribers”µÄ°dONLNd~}ËâE)| later in this chapter).°dONLNdóèlõÎ(òlTWhen a user opens a document that contains a subscriber (with an update mode set to °dONLNdÎõlß§*
  10615. automatic), rΔ‡°dONLNd¯õ§ßÈ)8Geceives a new edition, and then closes the document without making any °dONLNd    ?ßl≥≥(∞lchanges to the fiJ¿°dONLNd    Pߥ≥Ô)HFle, you should update the document and simply allow the user to close °dONLNd    ñ≥løw(ºlit. } °dONLNd    ö≥wø}) Y=†°dONLNd    õ≥}ø◊)ou do not need to prT °dONLNd    Ø≥◊øÄ)Z&ompt the user to save changes to the fio`°dONLNd    ÷≥Äøá)©le!`°dONLNd    Ÿ≥àøä).ˇº@ˇ ˇˇˇˇ@
  10616. ˇ·ˇ‚7^
  10617. 4H\, Palatino
  10618. .+ä"CHAPTER €`)\1,     Helvetica
  10619.     (@äThe Edition Manager4⁄ä˙(‡äUsing ◊P)The Edition Manager
  10620. ~¿(‡1
  10621. ‡)-a¿)22
  10622. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿
  10623. °dONLNd\ähü(eä<When closing a document that contains sections, you must unrj°dONLNd<\üh(eüegister each section (using .°dONLNdXhätú(qäthe ,
  10624. Courier°dONLNd\hút)UnRegisterSection°dONLNdmhtô)f# function) and dispose of each corrR`°dONLNdêhôtÌ)óesponding section r$¿°dONLNd£hÌtˇ)Tecor˜ °dONLNdßh˛t)d .°dONLNd©täÄ∑(}ä and alias r?‡°dONLNd¥t∏Ä ).ecor¥@°dONLNd∏t Ä’)d. .°dONLNdºåäòb(ïä$err := UnRegisterSection (sectionH);°dONLNd·§ä∞û*The °dONLNd§û∞)UnRegisterSection°dONLNdˆ§∞0)f  function rR`°dONLNd§0∞ä),emoves the section r$¿°dONLNd§ä∞ú)Zecor$¿°dONLNd§ú∞¨)d fr˜ °dONLNd§´∞È)om the list of .°dONLNd-∞äºç(πärE°dONLNd.∞麴)egisterî °dONLNd5∞´º4)!ed sections and unlinks itself frŸ`°dONLNdV∞4ºh)â om the shar”†°dONLNda∞hºå)4ed contr˜Ä°dONLNdi∞庱)$    ol block.°dONLNds¬äŒ∏(Àä Listing 1-3 @°dONLNd~¬πŒ[)/& illustrates how to open an existing fi‡°dONLNd•¬\Œ…)£le that contains sections. D`°dONLNd¿¬…Œ)m
  10625. As described °dONLNdÕŒä⁄¶(◊äearlier ‡°dONLNd‘Œ¶⁄„), you should rk¿°dONLNd‚Œ„⁄c)=etrieve the section and alias rí°dONLNdŒc⁄{)Äesour⁄@°dONLNdŒ{⁄„)ces, connect the pair thri °dONLNdŒ‰⁄
  10626. )i    ough the °dONLNd(⁄äʶ(„äalias fiİdONLNd0⁄ßʯ)eld of the section r<İdONLNdD⁄¯Ê
  10627. )Qecor∞‡°dONLNdH⁄
  10628. Ê,)d, and r˛¿°dONLNdP⁄,ÊÔ)",egister the section with the Edition Managerÿ°dONLNd|⁄ÔÊ)√. TherX¿°dONLNdÇ⁄    Ê)e °dONLNdÑÊäÚí(ÔäarE°dONLNdÜÊìÚ¬)    
  10629. e many difmİdONLNdêʬڌ)/ferP°dONLNdìÊŒÚ#) ent techniques for r‹†°dONLNdßÊ#ÚQ)U etrieving r¡`°dONLNd≤ÊQÚi).esour    †°dONLNd∑ÊjÚ)'ces; this listing shows one technique. °dONLNdfiÚä˛j(˚ä3If an alias was out of date and was updated by the π@°dONLNdÚj˛‚)‡Alias Manager during the r!°dONLNd+Ú„˛)y esolve, the .°dONLNd7˛ä
  10630. ˝(äEdition Manager sets the °dONLNdP˛˝
  10631. W)saliasWasUpdated°dONLNd_˛W
  10632. ®)Z parameter of the °dONLNdq˛®
  10633. )QRegisterSection°dONLNdIJ
  10634. )Z .°dONLNdÅ
  10635. ä±(ä@function to TRUE. This means that you should save the document. @°dONLNd¡
  10636. ≤Í(≤ AdditionallyØ °dONLNdÕ
  10637. È)7, your °dONLNd‘ä"C(ä+application must maintain its own list of r`°dONLNdˇC"`)πegisterŒÄ°dONLNd`")(ed sections for each open document that °dONLNd."ä.Ÿ(+äcontains sections. Ë °dONLNdA"Ÿ.fl)OY®†°dONLNdB"fl.˙)Bou use this list to write out new editions for updated publishers °dONLNdÑ.ä:‡(7äwithin a document.
  10638. \H`4]H_"]Ha
  10639. ˇ·ˇ‚7^
  10640.     °dONLNdˇˇ*# Listing 1-3°dONLNdóRŒ]p)D&Opening a document containing sections
  10641. .°dONLNdæiäu
  10642. (rä@PROCEDURE OpenExistingDocument(thisDocument: MyDocumentInfoPtr);°dONLNdÖäëú*VAR°dONLNdìúü“+    sectionH:°dONLNdìün)~SectionHandle;°dONLNd%°ú≠Δ(™úaliasH:°dONLNd3°≠b)~ AliasHandle;°dONLNdAØúª¸(∏úaliasWasUpdated:°dONLNdXتJ)~Boolean;°dONLNdbΩú…‰(Δú registerErr:°dONLNduΩ…>)~OSErr;°dONLNd}Àú◊¿(‘úresID:°dONLNdäÀ◊J)~Integer;°dONLNdîŸúÂÃ(‚úthisone:°dONLNd£ŸÂJ)~Integer;°dONLNd≠ÁúÛ(únumberOfSections:°dONLNd≈ÁÛJ)~Integer;°dONLNdœıú¿(˛úaName:°dONLNd‹ıD)~Str255;°dONLNdÂä®(äBEGIN°dONLNdÏú+
  10643. +={Set the curResFile to be the resource fork of thisDocument.}°dONLNd+-ú9å*(UseResFile(thisDocument^.resForkRefNum);ˇ ‰@ˇ ˇˇˇˇ@
  10644. ˇ·ˇ‚7^
  10645. 4*\˜, Palatino
  10646. .+l"CHAPTER €`)\1,     Helvetica
  10647.     (@lThe Edition Manager4⁄*˙¯
  10648. (‡*1 )-c)23
  10649.     )9Using ◊P)The Edition Manager
  10650. (ÔlDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯,
  10651. Courier
  10652. .°dONLNd\~hÄ(e~+{Find out the number of section resources.}°dONLNd-j~v™*2numberOfSections := Count1Resources(rSectionType);ˇˇfd°dONLNdbÜ~í˜*@{In determining the number of section/alias resource pairs to } °dONLNd§î~†Ê*<{ get, this code only loops for as many sections it finds. }°dONLNd‚¢~Ƈ*;{ It is unusual to have more section resources than alias }°dONLNd∞~ºÏ*={ resources. Your code may want to check this and handle it }°dONLNd^æ~ Œ*8{ appropriately. You now have a count of the number of }°dONLNdòÃ~ÿ∫*
  10653. { section/°dONLNd•Ã∫ÿ⁄)<0alias resource pairs to get. Loop to get them, }°dONLNd◊⁄~Êz(„~*{ connect them, and register the section.}°dONLNdÙ~h*'FOR thisone := 1 TO numberOfSections DO°dONLNd,~ú*BEGIN°dONLNd4ê⁄+7sectionH := SectionHandle(Get1IndResource(rSectionType,°dONLNdu*+~ °dONLNdv*) °dONLNdx *h)   thisone));°dONLNdá,ê8‡(5ê8{If sectionH is NIL, something could be wrong with the }°dONLNd¬:êFb*#{ file. Be sure to check for this.}°dONLNdÈVêbÊ*9{Get the resource ID of the section and use this to get }°dONLNd%dêpz*'{ the alias with the same resource ID.}°dONLNdOrê~Ê*9GetResInfo(Handle(sectionH), resID, rSectionType, aName);°dONLNdãÄêåV*!DetachResource(Handle(sectionH));°dONLNdØéêö¬*3{Detaching is not necessary, but it is convenient.}°dONLNdÊ™ê∂⁄*7aliasH := AliasHandle(Get1Resource(rAliasType, resID));°dONLNd ∏ꃇ*8{If aliasH is NIL, then there could be something wrong }°dONLNd[Δê“ò*,{ with the file. Be sure to check for this.}°dONLNdã‚êÓJ*DetachResource(Handle(aliasH));°dONLNd≠긬*3{Detaching is not necessary, but it is convenient.}°dONLNd‰ ên*%{Connect section and alias together.}°dONLNd ê&2*sectionH^^.alias := aliasH;°dONLNd+6êB*{Register the section.}°dONLNdEDêP‘*6registerErr := RegisterSection(thisDocument^.fileSpec,°dONLNdÅRΔ^fi+6    °dONLNdàR¸^)6 °dONLNdåR2^8)6 °dONLNdéRD^Ï) sectionH, aliasWasUpdated);°dONLNdÆnêz‘(wê6{The RegisterSection function may return an error if }°dONLNdÁ|êàÚ*;{ a section is not registered. This is not a fatal error. }°dONLNd%äêñ¬*3{ Continue looping to register remaining sections.}ˇZ@ˇ ˇˇˇˇ@
  10654. ˇ·ˇ‚7^
  10655. 4H\, Palatino
  10656. .+ä"CHAPTER €`)\1,     Helvetica
  10657.     (@äThe Edition Manager4⁄ä˙(‡äUsing ◊P)The Edition Manager
  10658. ~¿(‡1
  10659. ‡)-a¿)24
  10660. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿,
  10661. Courier
  10662. .°dONLNd\Æh(eÆ<{Add this section/alias pair to your internal bookkeeping. }°dONLNd?jÆv*;{ The AddSectionAliasPair is a routine to accomplish this.}°dONLNd}xÆÑÏ*5MyAddSectionAliasPair(thisDocument, sectionH, resID);°dONLNd∂îÆ†Ï*5{If the alias has changed, make note of this. It is }°dONLNdÓ¢ÆÆ*<{ important to know this when you save. AliasHasChanged is }°dONLNd3æÆ h*{ a routine that will do this.}°dONLNdUÃÆÿ⁄*2IF aliasWasUpdated THEN AliasHasChanged(sectionH);°dONLNdâ⁄úÊÿ(„ú
  10663. END; {for}°dONLNdîËäÙ2(ÒäEND;  {OpenExistingDocument}
  10664. H!4H! ä
  10665. ˇ·ˇ‚7^
  10666. ˇˇ◊.ˇ◊°dONLNd±
  10667. äı*&
  10668. Reading and WP–°dONLNdæ
  10669. ı\)kriting a Sectionˇˇˇˇˇˇ®(1
  10670. °dONLNdœ!ä-ê(*äY@İdONLNd–!ê-—)Iour application writes publisher data to an edition. New publisher data rÛİdONLNd!—-(*— eplaces the °dONLNd%-ä9ì(6äprG °dONLNd'-î9Y)
  10671. -evious contents of the edition, making the pr£Ä°dONLNdT-Y9‹)≈evious edition information irr– °dONLNdr-‹9 )É etrievable. °dONLNd~9äEê(BäY@İdONLNd9êE⁄)our application r+†°dONLNdê9⁄E
  10672. )J eads data fr≈°dONLNdú9
  10673. E˚)35om an edition for each subscriber within a document. °dONLNd“KäW6(Tä&The following sections describe how to,
  10674.  
  10675. Zapf Dingbats
  10676. °dONLNd˘`ägè*n
  10677. °dONLNd˚]ñi≥) use dif8 °dONLNd]¥i¿)fer†°dONLNd]¿i4) ent formats to write to or r‚@°dONLNd!]4iM)tead fr`İdONLNd']Niã)
  10678. om an edition
  10679. °dONLNd5räyè(xän
  10680. °dONLNd7oñ{=) (open an edition to initiate writing or rûİdONLNd_o={[)ßeading
  10681. °dONLNdfÑäãè(ään
  10682. °dONLNdhÅñç„) set a format mark
  10683. °dONLNdzñäùè(úän
  10684. °dONLNd|ìñü )
  10685. write to or r#°dONLNdâìÀü‰)5ead fr°@°dONLNdèì‰ü!)
  10686. om an edition
  10687. °dONLNdù®äØè(Æän
  10688. °dONLNdü•ñ±^) 0close an edition after successfully writing or rEİdONLNdœ•_±ì)… eading data
  10689. œH÷4–H÷ —ä—
  10690. ˇ·ˇ‚7^
  10691. °dONLNd€¬ä–˝(ÃäFormats in an Editionˇˇˇˇˇˇ(Ã1
  10692. °dONLNdÒ÷ä‚ê(fläY@İdONLNdÚ÷ê‚S).ou can write data to an edition in several dif °dONLNd ÷S‚_)√fer˚†°dONLNd#÷^‚fl) ent formats. These formats arˇ °dONLNd@÷fl‚)Å e the same °dONLNdK‚äÓº(Îä as ClipboarȰdONLNdV‚ºÓ)2d formats. Clipboar@ °dONLNdi‚ÓI)W d formats ar0@°dONLNdu‚IÓ£)6e indicated by a four¸°dONLNdä‚£Ó‰)Z-character tag. °dONLNdõÙäê(˝äT∫¿°dONLNdúÙè≤)ypicallyË¿°dONLNd§Ù±î)"4, when a user copies data, you identify the Clipboar£Ä°dONLNdÿÙï)‰d formats and then write °dONLNdÒä ‚(    äthe data to scrap. W¿°dONLNd‚ K)Xith the Edition Manager»`°dONLNdJ )h+, when a user decides to publish data, you °dONLNdG äÊ(äidentify the Clipboar∂@°dONLNd\ Êπ)\1d formats and then write the data to an edition. ¿°dONLNdç ∫¿)‘Y“@°dONLNdé ø¯)
  10693. ou can write °dONLNdõä$$(!ä#multiple formats of the same data. °dONLNdø*ä6<*(For an edition, you should write your pr&`°dONLNdÁ*=6Q)≥eferr≈ °dONLNdÏ*Q6â) ed formats fiΔ†°dONLNd˘*â6)8"rst. In general, to write data to °dONLNd6äB˜(?äTan edition, your application should use either 'TEXT' format or 'PICT' format. This °dONLNdoBäN* allows your application to sharö¿°dONLNdéBN∫)â&e data with most other applications. TÕ†°dONLNd¥BπN)¶o subscribe to an °dONLNdΔNäZK(Wä-edition, your application should be able to r İdONLNdÛNLZÀ)¬ead both 'TEXT' and 'PICT' fis¿°dONLNdNÀZ)les. In addition, °dONLNd"ZäfÂ(cäNyour application can write any other private formats that you want to support.°dONLNdqläx∞*Clipboar,°dONLNdyl±xÁ)' d formats ar °dONLNdÖlÁx≤)6-e described in the Scrap Manager chapter in V¶¿°dONLNd≤l±x◊)     olume I. °dONLNdº~ääë(áäA∫†°dONLNdΩ~ëäÙ) few special formats arM@°dONLNd‘~ıä
  10694. )de defiâ°dONLNd⁄~
  10695. äW)ned as constants.ˇ@ˇ ˇˇˇˇ@
  10696. ˇ·ˇ‚7^
  10697. 4*\˜, Palatino
  10698. .+l"CHAPTER €`)\1,     Helvetica
  10699.     (@lThe Edition Manager4⁄*˙¯
  10700. (‡*1 )-c)25
  10701.     )9Using ◊P)The Edition Manager
  10702. (ÔlDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯,
  10703. Courier
  10704. .°dONLNd\lhä(elCONST°dONLNd\êh )$kPublisherDocAliasFormat°dONLNd(\2hh)¢    = 'alis';°dONLNd2\hh¯)6{alias record from the }°dONLNdYjhvÚ*{ edition to publisher}°dONLNdqxlÑ¿(ÅlkPreviewFormat°dONLNdäx2Ñh)Δ    = 'prvw';°dONLNdîxhÑ⁄)6{'PICT' thumbnail }°dONLNd∂Ühíû*    { sketch}°dONLNd¿îl†“(ùlkFormatListFormat°dONLNd‹î2†h)Δ    = 'fmts';°dONLNdÊîh†Ï)6{lists all available }°dONLNd ¢hƧ*
  10705. { formats}ˇˇú⁄°dONLNd∫lΔ(√lThe ˇ˛÷é⁄°dONLNd∫ÄΔ)kPublisherDocAliasFormatˇˇú⁄⁄°dONLNd2∫ΔÍ)ê2 ('alis') format is written by the Edition ManagerFJ°dONLNdd∫ÍΔ¯)⁄. It .°dONLNdiΔl“ù(œl
  10706. is an alias r…İdONLNdvΔù“Ø)1ecor=‡°dONLNdzΔ∞“ø)d frÚİdONLNd~Δø“G)om the edition to the publisherW†°dONLNdùΔI“Ñ)ä
  10707. ’s document. 7İdONLNd™ΔÑ“Ô);Appended to the end of °dONLNd¡“lfi!(€l,the alias is the section ID of the publisherá¿°dONLNdÌ“!fiˆ)µ0, which the Edition Manager uses to distinguish °dONLNdfilÍ@(Ál1between multiple publishers to a single edition. ‹`°dONLNdNfi@ÍF)‘Yú‡°dONLNdOfiFÍ…)ou should discourage users frx@°dONLNdlfi…ÍŸ)Éom °dONLNdoÍlˆ5(Ûl,making multiple copies of the same publisherïİdONLNdõÍ5ˆK)…. See ËİdONLNd°ÍKˆÀ)“Duplicating Publishers and °dONLNdΩˆl£(ˇl Subscribers”W†°dONLNd…ˆ§k)80 later in this chapter for detailed information..°dONLNd˙lÄ(lThe °dONLNd˛Ä‘)kPreviewFormat°dONLNd ‘fl)T; ('prvw') format should be written by any application that .°dONLNdGl §(l
  10708. publishes lar$°dONLNdT• Ä)90ge amounts of data that may be slow to draw a pr¶`°dONLNdÑÄ ö)€eview4@°dONLNdâö ˜). This format holds a °dONLNdü l,u()lprG °dONLNd° v,W)
  10709. 5eview of the edition data that is displayed in the pr~ °dONLNd÷ W,|)·eview ar<°dONLNdfi },Û)&ea of the subscriber dialog °dONLNd˙,l8(5l'box. This format is actually a 'PICT' fi£°dONLNd",8Î)•3le that is generated by the publishing application °dONLNdU8lD”(Aland displays well in a rU°dONLNdm8”DT)gectangle of 120 by 120 pixels. `°dONLNdå8UD[)ÇYÿ‡°dONLNdç8ZD’)ou can also use this 'PICT' fiM@°dONLNd´8÷DÎ)|le to °dONLNd±DlPp(Ml;display subscriber data within a document (to save space). ˇˇy.°dONLNdÌVlbr*Tï°dONLNdÓVqb¢) o draw a pr“ưdONLNd˘V¢bî)16eview in the 'prvw' format, the Edition Manager calls ˇ˛kNò°dONLNd/Vïb◊)Û DrawPictureˇˇyò°dONLNd:V◊b¯)B with a .°dONLNdBbln†(kl 120 by 120 r€¿°dONLNdNb†nœ)4 ectangle. T†@°dONLNdYbœn)/ o draw a pr¬@°dONLNddbnÿ)30eview in the 'PICT' format, the Edition Manager ˇˇ∂.°dONLNdînlzƒ(wlexamines the picturæÑ°dONLNdßnƒzˇ)Xe’s bounding r˝°dONLNdµnˇzQ);ectangle and calls ˇˇ"6>°dONLNd»nRzî)S DrawPictureˇˇ∂>°dONLNd”nîz∫)B     with a r‘°dONLNd‹n∫z¯)&ectangle that .°dONLNdÍzlÜ≥(Élscales the picturb‡°dONLNd˚z≥܃)Ge prs†°dONLNdˇzƒÜá).oportionally and centers it in a 120 by 120 arô °dONLNd-záÜï)√ea. .°dONLNd2ålòÄ(ïlThe °dONLNd6åÄòÊ)kFormatListFormat°dONLNdGåÊò®)f. ('fmts') format is a virtual format that is rR`°dONLNduå®òÊ)¬ead but never .°dONLNdÉòl§X(°l<written. It is a list of all the formats and their lengths. `°dONLNdøòY§ı)Ì$Applications can use this format in .°dONLNd„§l∞§(≠l
  10710. place of the °dONLNd§§∞)8EditionHasFormat°dONLNd§∞h)` function (described in °dONLNd§h∞‡)d“Choosing Which Edition .°dONLNd0∞lºµ(πlFormat to Read”ÿ‡°dONLNd?∞µº=)I! later in this chapter), which pr‚İdONLNd`∞=ºn)à ovides a pr– °dONLNdk∞nºÀ)1ocedural interface to °dONLNdźl»Á(≈ldetermine which formats arb °dONLNdõºÁ»){ e available.°dONLNd®Œl⁄÷(◊lIf your application can rÓ@°dONLNd¡Œ÷⁄)jead two or morŸ °dONLNdœŒ⁄ı)D4e of the available formats, use 'fmts' to determine °dONLNd⁄lÊo(„l>the priority of these formats for a particular edition. The or¸¿°dONLNdA⁄oÊ©(„oder of 'fmts' r≤ °dONLNdP⁄™Ê¥);eflàİdONLNdS⁄µÊ·) ects the orY†°dONLNd^⁄‚ÊÛ)-der °dONLNdbÊlÚ€(Ôlin which the formats wer^İdONLNdzÊ€Ú)o
  10711. e written..°dONLNdÖ¯lÄ(lThe °dONLNdâ¯Ä‡)FormatsAvailable°dONLNdô¯‡#)` data type defi°dONLNd®¯#?)Cnes a rR`°dONLNdد?Q)ecor$¿°dONLNd≥¯Q∫)d for the 'fmts' format. °dONLNdÕlP(l&TYPE FormatsAvailable = ARRAY[0..0] OF°dONLNdı~*¢+RECORD°dONLNd˛,ê8¿+theType:°dONLNd    
  10712. ,ÿ8)H FormatType;°dONLNd    ,28⁄)Z{format type for an edition}°dONLNd    9:êFÃ(Cê
  10713. theLength:°dONLNd    G:ÿF)HLongInt;°dONLNd    T:2F‘)Z{length of edition format }°dONLNd    {H2T\*{ type}°dONLNd    ÑV~bñ(_~END;.°dONLNd    ânlzÁ(wlUFor example, an edition container may have a format type 'TEXT' of length 100, and a °dONLNd    fizlÜÒ* !format type 'styl' of length 32. İdONLNd    ˇzÚܢ)ÜAZ °dONLNd
  10714. z˘ÜÀ)2 subscriber to this edition can open it and then r@°dONLNd
  10715. 2zÃÜÓ)”ead the °dONLNd
  10716. :Ülíã(èlGformat type 'fmts' to list all available formats. In this example, it r*İdONLNd
  10717. ÅÜåíÛ(èåeturns 16 bytes: 'TEXT' °dONLNd
  10718. ôílû·(õl$00000064 'styl' $00000020.ˇ@ˇ ˇˇˇˇ@
  10719. ˇ·ˇ‚7^
  10720. 4H\, Palatino
  10721. .+ä"CHAPTER €`)\1,     Helvetica
  10722.     (@äThe Edition Manager4⁄ä˙(‡äUsing ◊P)The Edition Manager
  10723. ~¿(‡1
  10724. ‡)-a¿)26
  10725. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿
  10726. jHp4jHp käk
  10727. ˇ·ˇ‚7^
  10728. °dONLNd\äjÚ(fäOpening an Editionˇˇˇˇˇˇ(f1
  10729. .°dONLNdpä|œ(yäFor a publisher¬†°dONLNd"pŒ|ı)D
  10730. , use the ,
  10731. Courier¬†°dONLNd,pı|I)'OpenNewEdition¬†°dONLNd:pI|)T0 function to initiate the writing of data to an .°dONLNdj|äà´(Öäedition..°dONLNdsî䆬*4err := OpenNewEdition (publisherSectionH, fdCreator,°dONLNdØ¢Æ+~ °dONLNd∞¢Æ) °dONLNd±¢Æ‡)"publisherSectionDocument, refNum);ˇˇe¯°dONLNd‘∫äΔù(√äThe ˇ˛1˯°dONLNdÿ∫ùΔ)publisherSectionHˇˇe¯¯°dONLNdÈ∫Δ–)f/ parameter is the publisher section that you ar˰dONLNd∫–Δ)Õe writing to the °dONLNd)Δ䓃(œä
  10732. edition. The °dONLNd6Δƒ“˙):    fdCreator°dONLNd?Δ˙“h)6 parameter is the Finder
  10733. .°dONLNdˇˇ(Àh™
  10734. .U°dONLNdjΔp“z+ cr'`°dONLNdmΔz“)
  10735. #eator type of the new edition icon.°dONLNdëÿä‰û(·äThe °dONLNdïÿû‰.)publisherSectionDocument°dONLNd≠ÿ.‰˙)ê- parameter is the document that contains the .°dONLNd⁄‰ä¥(Ìä    publisherÓ‡°dONLNd„‰≥2)). This parameter is used to crS`°dONLNd‰3r)Äeate an alias fr°°dONLNd‰r˙)?om the edition to the publisher °dONLNd0‰¸)ä’s .°dONLNd3串(˘ädocument. If you pass NIL!†°dONLNdL˛¸)t for !†°dONLNdQ¸ü)publisherSectionDocument!†°dONLNdiü¸ )ê, an alias is not made in °dONLNdɸäΔ(ä
  10736. the edition fi°dONLNdë¸ΔË)<le. The °dONLNdô¸Ë )"refNum°dONLNdü¸ D)$  parameter rR`°dONLNd´¸Dw)8 eturns the r$¿°dONLNd∑¸wâ)3efer˜ °dONLNdª¸à)ence number for the edition. °dONLNdŸäœ(äFor a subscriber¬†°dONLNdÈŒı)D
  10737. , use the ¬†°dONLNdÛı7)' OpenEdition¬†°dONLNd˛7¶)B function to initiate the rï°dONLNd¶Ú)oeading of data frg`°dONLNd*Ú)Lom an .°dONLNd0ä&´(#äedition..°dONLNd92ä>∞*1err := OpenEdition (subscriberSectionH, refNum); °dONLNdkJäVû*The °dONLNdoJûV
  10738. )subscriberSectionH°dONLNdÅJ
  10739. Vµ)l' parameter is a handle to the section rR`°dONLNd®JµV«)´ecor$¿°dONLNd¨J«V)d for a given °dONLNd∫Väb¬(_ä
  10740. section. The °dONLNd«V¬bÊ)8refNum°dONLNdÕVÊb)$  parameter rR`°dONLNdŸVbQ)8 eturns the r$¿°dONLNdÂVQbc)3efer˜ °dONLNdÈVbbfi)ence number for the edition..°dONLNdhätÃ(qäThe user may r‰@°dONLNdhÃt})B'ename or move the edition in the Finder’¿°dONLNd;h}tô)±. BeforIİdONLNdBhötfl)e writing to or rµ`°dONLNdShflt)E eading data °dONLNd_täÄë(}äfrò‡°dONLNdatëÄH)(om an edition, the Edition Manager verifiÀ†°dONLNdätHÄfi)∑#es the name of the edition. This pr„`°dONLNd≠tfiÄ)ñ    ocess is °dONLNd∂Ääåç(âärE°dONLNd∑Äéå¢)eferr„¿°dONLNdºÄ¢åΔ)    ed to as >°dONLNd≈Ä«åÎ)%synching°dONLNdÕÄÏå)%
  10741.  or synchr%@°dONLNd◊Äåã),onization. Synching ensur°dONLNdÄãå)ses that the Edition Manager0°dONLNd Äå){’s °dONLNdåäò(ïäexisting edition names corr+†°dONLNd)åò])xespond to the FinderäİdONLNd=å^ò)\&’s existing edition names by updating °dONLNdcòä§±(°ä    the contrõ‡°dONLNdlò±§ÿ)'
  10742. ol block. 
  10743. ¬H…4√H… ƒäƒ
  10744. ˇ·ˇ‚7^
  10745. °dONLNdwµä√’(øä Format Marksˇˇˇˇˇˇ(ø1
  10746. °dONLNdÑ…ä’Õ(“äIEach format has its own mark. The mark indicates the next position of a r¢Ä°dONLNdÕ…Õ’(“Õ
  10747. ead or write °dONLNd⁄’ä·‹(fiäoperation. Initially¨†°dONLNdÓ’€·{)Q&, a mark automatically defaults to 0. ‡°dONLNd’|·ô)°After rp†°dONLNd’ô·)eading or writing data, the °dONLNd7·äÌx(Íä9format mark is set past the last position written to or r¢Ä°dONLNdp·xÌë)Óead fr ¿°dONLNdv·íÌ)om. The mark is similar to °dONLNdëÌ䢑(ˆäthe File Manager÷@°dONLNd°Ì’˘)K’s currâİdONLNd®ÌÒ˘)ent r´‡°dONLNd≠Ì˘ ).ead or write position marker for a data fork. ^‡°dONLNd€Ì ˘    )≈Any time that .°dONLNdÈ˘ä,(ä&an edition is open (after calling the °dONLNd˘,n)¢ OpenEdition°dONLNd˘nç)B or the °dONLNd"˘ç·)OpenNewEdition°dONLNd0˘·)T  function), .°dONLNd<ä}(ä8any of the marks for each format can be queried or set. °dONLNduä#ê*Tµ¿°dONLNdvè#»)o set the curr†°dONLNdÑ…#Ω):9ent mark for a section format to a new location, use the .°dONLNdΩ#ä/(,äSetEditionFormatMark°dONLNd—#/-)x  function. °dONLNd›;äG‘(Dä7err := SetEditionFormatMark (whichEdition, whichFormat,°dONLNdI,U2+¢ °dONLNdI2UÄ)
  10748.  setMarkTo); .°dONLNd-aämê(jäTµ¿°dONLNd.aèmù)o fi∏°dONLNd2aùm¬)nd wher‹ °dONLNd9a¬m„)%e a curr‘¿°dONLNdAa„mé)!(ent mark is for a format in an edition fi‡°dONLNdjaèmΩ)¨ le, use the .°dONLNdvmäy(väGetEditionFormatMark°dONLNdämy-)x  function. °dONLNdñÖäë‘(éä7err := GetEditionFormatMark (whichEdition, whichFormat,°dONLNd◊ì,ü2+¢ °dONLNdÿì2ü8) °dONLNdŸì8üå)currentMark); ˇ @ˇ ˇˇˇˇ@
  10749. ˇ·ˇ‚7^
  10750. 4*\˜, Palatino
  10751. .+l"CHAPTER €`)\1,     Helvetica
  10752.     (@lThe Edition Manager4⁄*˙¯
  10753. (‡*1 )-c)27
  10754.     )9Using ◊P)The Edition Manager
  10755. (ÔlDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯
  10756. j*p¯4j*p¯ klk¯
  10757. ˇ·ˇ‚7^
  10758. °dONLNd\ljæ(fl
  10759. Reading and W(°dONLNd
  10760. \æj!)Rriting Edition Dataˇˇˇˇˇˇ(fÚ1
  10761. °dONLNd!pl|v(ylWÛ`°dONLNd"pu|fi)    ith the Edition Manager≥°dONLNd9pfi| )i , you can r≈`°dONLNdDp |‰).3ead or write data a few bytes at a time instead of °dONLNdw|làÒ(ÖlYputting data into one block as the Scrap Manager does. This model is similar to the data °dONLNd–àlî * fork of a Macintosh fi¿°dONLNdÊàÀî◊)_le. ã °dONLNdÍà◊î›) YK†°dONLNdÎà›î)ou can rŒ‡°dONLNdÛàî»)#.ead sequentially by setting the mark to 0 and °dONLNd!îl†o(ùlrE°dONLNd"îp†¡)epeatedly calling r»Ä°dONLNd5O)Q ead, or you can jump to a specifiΩ`°dONLNdVîP†_)èc ofI`°dONLNdZî`†‹)fset by setting the mark ther&¿°dONLNdwÂ)|e. °dONLNdz†l¨M(©l3The Edition Manager also adds the capability to strǰdONLNd≠†M¨È)·"eam multiple formats by keeping a °dONLNdœ¨l∏È(µlVseparate mark for each format. This allows you to write a few bytes of one format and °dONLNd%∏lƒZ* 7then write a few bytes of another format, and so forth.°dONLNd] l÷°*EOnce you have opened the edition container for a particular publisher’ °dONLNd¢ †÷Â(”†, you can begin .°dONLNd≤÷l‚(fll%writing data to the edition. Use the ,
  10762. Courier°dONLNd◊÷‚X)§ WriteEdition°dONLNd„÷X‚˜)H% function to write publisher data to .°dONLNd‚lÓù(Îl an edition. .°dONLNd˙l¯*Berr := WriteEdition (whichEdition, whichFormat, buffPtr, buffLen);°dONLNdXlÄ*The °dONLNd\Ä») WriteEdition°dONLNdh»?)H function writes the specifi°dONLNdÑ?Õ)w ed format (beginning at the currR`°dONLNd§Õ˜)é    ent mark .°dONLNd≠l*–('lfor that format type) frnİdONLNd≈–*)d
  10763. om the bufJ`°dONLNdœ*k)0fer pointed to by the bufdONLNdËk*÷)kfPtr parameter up to buf.@°dONLNd◊*Ì)lfLen °dONLNd*l6à(3lbytes. °dONLNd
  10764. <lHÁ*UAfter you open the edition container for a subscriber and determine which formats to .°dONLNdbHlTp* rR`°dONLNdcHpT®)
  10765. ead, use the R`°dONLNdpH®TÍ)8 ReadEditionR`°dONLNd{HÍT!)B function to r$¿°dONLNdâH!Tr)7ead edition data. °dONLNdú`llÚ(ilAerr := ReadEdition (whichEdition, whichFormat, buffPtr, buffLen);°dONLNdfixlÑÄ*The °dONLNd‚xÄѬ) ReadEdition°dONLNdÌx¬ÑÓ)B  function rR`°dONLNd¯xÓÑx),eads the data with the specifiR`°dONLNdxxÑÔ)äed format (whichFormat) °dONLNd.Ñlêt(çlfrR`°dONLNd0ÑtêÏ)om the edition into the buf$¿°dONLNdKÑÏê˘)xferg`°dONLNdNѯê) . The g`°dONLNdTÑêS) ReadEditiong`°dONLNd_ÑSêù)B function begins r9¿°dONLNdqÑùê‹)Jeading at the .°dONLNdêlú~(ôlcurrذdONLNdÉê~ú;)+ent mark for that format and continues to rÒ†°dONLNdÆê;úv)Ω
  10766. ead up to bufÕ °dONLNdªêvúŸ);fLen bytes. The actual .°dONLNd“úl®∑(•lnumber of bytes rR`°dONLNd„ú∑®ÿ)Kead is r$¿°dONLNdÎúÿ®)!eturned in the $¿°dONLNd˙ú®C)AbuffLen$¿°dONLNdúC®u)*
  10767.  parameterg`°dONLNd út®£)1 . Once the g`°dONLNdú£®Õ)/buffLeng`°dONLNdúÕ®œ)* .°dONLNd®l¥†(±l parameter rV°dONLNd)®†¥ç)45eturns a value smaller than the value you have specifiƒÄ°dONLNd_®ç¥Æ)Ìed, therL@°dONLNdg®Ø¥Õ)"e is no .°dONLNdo¥l¿«(Ωladditional data to rR`°dONLNdÉ¥«¿)[
  10768. ead, and the R`°dONLNd꥿D); ReadEditionR`°dONLNdõ¥D¿p)B  function r$¿°dONLNd¶¥p¿ï),    eturns a $¿°dONLNdØ¥ï¿≥)%noErr$¿°dONLNd¥¥≥¿π) r˜ °dONLNd∂¥∏¿È) esult code. 
  10769. fi*¯4fl*¯ ‡l‡¯
  10770. ˇ·ˇ‚7^
  10771. .°dONLNd√—lflŒ(€lClosing an Editionˇˇˇˇˇˇ(€Ú1
  10772. .°dONLNd÷ÂlÒ¶(Ól When you arR`°dONLNd·¶Ò):e done writing to or r$¿°dONLNd˜ÂÒC)\eading data fr˜ °dONLNdÂBÒ™)@om an edition, call the ˜ °dONLNd™ÒÚ)h CloseEdition˜ °dONLNd)ÂÚÒÙ)H .°dONLNd*Òl˝ë(˙lfunctioné@°dONLNd2Òë˝ñ)%. .°dONLNd5    lÜ(l/err := CloseEdition (whichEdition, successful);.°dONLNde!l-◊*OEach time a user edits a publisher within a document, you must update the modifi5`°dONLNdµ!ÿ-ı(*ÿcation °dONLNdº-l9¬(6ldate in the section rÏ`°dONLNd—-¬9‘)Vecor`¿°dONLNd’-’9Ô)Ad (even if the data is not yet written). When the update mode is °dONLNd9lE∞(Blset to Manually¿°dONLNd%9∞E)D, the user can compar3°dONLNd:9EC)^ e the modifi4`°dONLNdF9CEfi)5%cation dates for a publisher and its °dONLNdkElQ_(Nl6edition in the publisher options dialog box. One modifi °dONLNd¢E`QË)Ùcation date indicates when the °dONLNd¡Ql]∂(Zlpublisher last wr0°dONLNd“Q∑]w)K,ote data to the edition, and the other modifiŒ†°dONLNdˇQw]Ô)¿cation date indicates when °dONLNd    ]li(fl'the publisher section was last edited. .°dONLNd    Bol{à*If the °dONLNd    Ioà{ƒ)
  10773. successful°dONLNd    Soƒ{y)<( parameter for a publisher is TRUE, the °dONLNd    {oy{¡)µ CloseEdition°dONLNd    áo¡{È)H
  10774.  function .°dONLNd    ë{láØ(ÑlHmakes the newly written data available to subscribers and sets the modifiH¿°dONLNd    ⁄{∞áÓ(Ñ∞cation date in ˇˇ√6.°dONLNd    Èálì}(êlthe ˇˇI¢C6°dONLNd    Ìá~ì¢)mdDateˇˇ√6C6°dONLNd    Ûá¢ì™)$ fil°dONLNd    ˆá´ì)    eld of the edition to corr®⁄°dONLNd
  10775. áìq)kespond to the modifiÚ|°dONLNd
  10776. $áqìÓ)[cation date of the publisherº¥°dONLNd
  10777. @áÔì˜)~’s .°dONLNd
  10778. Cìlüë(úl    section r≠İdONLNd
  10779. Lìëü£)%ecor!‡°dONLNd
  10780. Pì§ü)d. If the two dates difk`°dONLNd
  10781. gìü)^feræ °dONLNd
  10782. jì
  10783. üÙ) 4, the Edition Manager sends a Section Read event to °dONLNd
  10784. ûül´ã(®lall currˇ¿°dONLNd
  10785. ¶üã´“)ent subscribers. ˇ-∏@ˇ ˇˇˇˇ@
  10786. ˇ·ˇ‚7^
  10787. 4H\, Palatino
  10788. .+ä"CHAPTER €`)\1,     Helvetica
  10789.     (@äThe Edition Manager4⁄ä˙(‡äUsing ◊P)The Edition Manager
  10790. ~¿(‡1
  10791. ‡)-a¿)28
  10792. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿
  10793. .°dONLNd\äh¶(eäIf the ,
  10794. Courier°dONLNd\¶h‚)
  10795. successful°dONLNd\‚hó)<) parameter for a subscriber is TRUE, the °dONLNd:\óhfl)µ CloseEdition°dONLNdF\flh)H
  10796.  function .°dONLNdPhät (qäsets the modifi=¿°dONLNd_hÀtG)Acation date of the subscriberC`°dONLNd|hHtv)} ’s section rı °dONLNdàhvtà).ecoriİdONLNdåhâtÆ)    d to corr⁄İdONLNdïhÆtÏ)%espond to the °dONLNd£täÄß(}ämodifi⁄`°dONLNd©tßÄ)cation date of the edition..°dONLNd≈Üäí(èäIf you cannot successfully rR`°dONLNd·Üí)vead fr$¿°dONLNdÁÜí«)(om or write data to an edition, set the $¿°dONLNdÜ«í)¨
  10797. successful$¿°dONLNdÜí)< .°dONLNdíäû (õäparameter to Fö†°dONLNd(í û+)@ALSE. For a publisher?@°dONLNd=í+û)a:, data is not written to the edition, but it should still °dONLNdwûä™(ßäWbe saved with the document that contains the section. When the document is next saved, °dONLNdŒ™ä∂H* -data can then be written to the edition. See  °dONLNd˚™I∂¢)ø“Closing an Edition ò`°dONLNd™¢∂Ó)YAfter Reading or ˇˇ%.°dONLNd ∂ä¬ï(øäW¬†°dONLNd!∂î¬≥)
  10798. riting”¬†°dONLNd(∂≥¬§)9 later in this chapter for additional information on the ˇ˝oT5∏°dONLNda∂•¬Ì)Ú CloseEditionˇˇ%5∏°dONLNdm∂̬)H  function. 
  10799. ÁHÌ4ËHÌ ËäË
  10800. ˇ·ˇ‚7^
  10801. ˇˇ◊.ˇ◊°dONLNdy÷äÁõ(„äCrè °dONLNd{÷õÁ)eating a Publisherˇˇˇˇˇˇ®(„1
  10802. °dONLNdéÌä˘ê(ˆäY@İdONLNdèÌê˘˘)ou need to support a CrD@°dONLNd¶Ì˘˘
  10803. )i:eate Publisher menu command in the Edit menu. When a user °dONLNd‡˘äY(ä.selects a portion of a document and chooses Cr¿‡°dONLNd˘Y°)œeate Publisher fr„ °dONLNd˘°ˆ)Hom this menu, you °dONLNd1äm(ä3should display the publisher dialog box on the userÃ`°dONLNddnÑ)‰’s scr¬‡°dONLNdjÑ∂) een. The Cr?@°dONLNdu∑)3eate Publisher menu °dONLNdâä›(äcommand should rO°dONLNdôfiÔ)T=emain dimmed until the user selects a portion of a document. .°dONLNd◊#ä/Ø(,äUse the °dONLNdfl#Ø/)%NewPublisherDialog°dONLNdÒ#/)l5 function to display the publisher dialog box on the .°dONLNd&/ä;ù(8äuser=¿°dONLNd*/û;¥)’s scr4@°dONLNd0/¥;ö)5een. This function is similar to the CustomPutFile pr‡¿°dONLNde/ö;∏)Êocedurx°dONLNdk/π;    )e described in the °dONLNd~;äG¨(DäStandar¥@°dONLNdÖ;¨GV)"'d File Package chapter in this volume. .°dONLNd≠Sä_V(\ä"err := NewPublisherDialog (reply);.°dONLNd–käw1*&The dialog box contains space for a prø°dONLNdˆk1w)ß0eview (a thumbnail sketch) of the edition and a °dONLNd&wäÉ(Ää\space for the user to type in the name of the edition in which to write the publisher data. °dONLNdÇÉäè¢* FigurR¿°dONLNdáÉ¢è∂)e 1-1c†°dONLNdåÉ∂èª)1c†°dONLNdçɪès)+ illustrates a sample publisher dialog box.
  10804. ≤H√4≥H√"≥H_
  10805. ˇ·ˇ‚7^
  10806.     °dONLNdˇˇ(∞ä Figure 1-11°dONLNdπ®Ã≥“)BA0°dONLNd∫®“≥D) sample publisher dialog box
  10807. .°dONLNd◊näzû(wäThe °dONLNd€nûz
  10808. )NewPublisherDialog°dONLNdÌn
  10809. zx)l function displays the prR`°dONLNdnxz§)n    eview (pr$¿°dONLNdn§zÈ),ovided by your .°dONLNdzäÜü(ÉäAapplication), a text box with the default name of the edition (pr3@°dONLNd_z†ÜÊ(Ɇovided by your °dONLNdnÜäí‚(èäQapplication), and handles all user input until the user clicks Publish or Cancel..°dONLNd¿òä§ë*Yï°dONLNd¡òê§)ou pass a new publisher rg`°dONLNd⁄ò§)peply r9¿°dONLNd‡ò§-)ecor  °dONLNd‰ò-§ò)d as a parameter to the   °dONLNd¸òò§)kNewPublisherDialog  °dONLNdò§)l .°dONLNd§ä∞±(≠ä    function.
  10810. ¬äV4√äVòÄ@6˛HHEÚÿˇˇˇˇˇˇ6˛≈ç蟬ˇ¸Ä√Ä√ü√ˇ‰ü√ˇ‰ò√dò√dò√dò√dò√dò√dò√dò√dò√dòÔ˘ˆˇ¸ÎdòʈÎdòÔ˘ˆÎdòʈÎdòÔ˘¿3¿˝Îd(ò¸Ä0?ÅÄ0¸˜IJ|¿˛d+ò¸ ¿ˆ˘ AÅÛ<«èá˜IJf¿˛d.ò¸ Õû31„3Ú¸AÉ3˛ÃÅˇΔ˘ˇ¡Éœ¯ffiyÁÄd/ò¸ Œ¸3˚˘ A„3ÃÃŒˇÜ˘!ÜlÕfÊû¿d+ò¸å¸3Ú AÉ3Ãë˘!Ülï|Δë¿d2ò¸ ?33Û3˚˘ AÉ3ÃÃ√Ä>˘!ÜlÕò`Δ¸Ã¿d.ò¸ 0333Ú AÉ3ÃÃ…Ä˘!ÜlÕò`Δ¿Ã¿d2ò¸ 1232˚˘ ¡ÒÛ «å«˘ˇ¡ÜlÕò`ΔƒÃ¿d'ò¸ <1„¸Úˇ¿˘˜ ÛÃï`Δxg¿dòÔ˘ˆÎdòʈÎdòÔ˘ˆÎdòʈˇ˛ÎdòÔ¯ˆˇ˛Îdò√d
  10811. òÔ÷dò√d
  10812. òÔ÷dòÌ?ÁˇÛdòÔ?Èˇ¯ÛdòÌ?Èˇ¯ÛdòÔ?Èˇ¯˘ˇ˛d"òÌ?U«?ˇˇ?˝ˇ¸¸ˆˇ¯(˘Äd"òÔ>™øõ˛ˇ?˝ˇ¸ıˇ¯D¯Äd#òÌ
  10813. ?ü08É&˛„˜ˇ¯Ç ¯@d$òÔ>ˇøè˝3?3˛ÃÕ˜ˇ˘ ¯@d(òÌ?«˝3?3> Ãܘˇ˚«ê *Ä@d+òÔ>ˇø„˛30?3<˛Ãœ˜ˇ ¯D ˛@d(òÌ?Û˝3ˇ3<˛Ãœ˜ˇ¯D  †¢Ä@d)òÔ>™ø≥˝3ø3<˛ÃÕ˜ˇ¯D ˛˛@d)òÌ?U«338É> ʡ¯| (àÄÄ@d&òÔ?¸ˇ?ˇˇÛˇ¸Ùˇ ¯ Q˛@d$òÌ?¸ˇ?ˇˇsˇ¸Ùˇ    ¯  ˛Ä@dòÔ?˘ˇáˇ     ˛@dòÌ?Èˇ¯ *††Ä@dòÔ È ˛¸@dòÌ È ˛à¸@dòÔ È ˛P¸@dò̠ȯÄdòÔ È˘ÄdòÌ È˘ˇ˛dòÔ ‡˛¿¿ÛÛdòÌ
  10814. !Ä¿¿ÛÛd!ò˜`˙
  10815. !@8x«á¯Ò„¿ÙÛdò˜x¯ !@dåÃÃÅôƒ`ÙÛd!ò˜,˙
  10816. !@p|ÃŒò¯√‡ÙÛdò˜4¯ !@8Ü«ôòΔ`ÙÛd!ò˜˙
  10817. !@ÃÃÅôòΔ`ÙÛdò˜¯ !@LÃÃIÅôòΔ`ÙÛd!ò˜˙
  10818.  ˇÄ8|«á¯¯c‡ÙÛdò˘ Ģ ÈÛdò˘¿˚ È˘ˇ˛dò˘ Ä@˘ È˘Ädò˘ Ä@˚ È¯Ädò˘@`˘ È ¯@dò˘`(˚ È ¯@d"ò˘0(˘ È  ¯Ä¿˛@d.ò˙ <˚ ™Ä¿˚ ı  ÃÄ¿˛@d,ò˙q„t˘!U@¿˚ ı Ãxqô„«¿@d1ò˙1t˚ ÄÄ8x«á≥«√Δfiı ÃÃ…∞Δf`@d/ò˙ d˘ !@dåÃÃÅΔffg ı Ã÷‡Δf`@d2ò˚˛˚
  10819.  ÄÄp|ÃŒܲf ı Ã¸q¿Δf`@d0ò˚˘ !@8Ü«áÊff ı Ã¿9‡Δf`@d2ò˚˚ ÄÄÃÃÅÜff ı Ãƒô∞Δf`@d/ò˚‡˛Ä¯ !U@LÃÃIÅÜ&ff ı ¯xqòc«¿@d1ò¸ɡѯ¸ ™Ä8|«áÉ«√Δı ˚@d'ò¸‡Ñ ˙ ˘Ú ˚@d&ò¸¯<帠˘Ú ¯@d!ò¸Äà0Ä˚ È¯Äd!ò˘Äà`¿˝ È˘Äd ò˙¸8ê‡˚ È˘ˇ˛dò˙«å0x¸ ÈÛdò˘pF n˙ ÈÛdò˘c¸ ÈÛdò˘9˙ ÈÛdò˙„Ä¿˝ ÈÛdò˚¿? ¿@˚ ÈÛdò˚`0˝ ÈÛdò˚0 ˚ ÈÛd#ò˚`0 ˝ È˘ˇ˛d!ò˚¿ˇ˚ È˘Äd"ò˚·¿ˇŬ˝ È¯Äd ò˚ÉÅÃc˚ È ¯@d&ò˚x1˝ È ¸@d%ò¸  0  ˛
  10820. ˚ È ¸@d)ò¸Aà`` |˝ È  Ä@d(ò˝    ‚ò¿¿ («˚ È 0Ä@d*ò˝    Mć (¡˝ È 8èò@d(ò˝    sć8@˚ È <ôôò@d*ò˝     Q¢`√ì0 ˝ È .ôôò@d(ò˝     lÄΔ00˚ È 'üôò@d*ò˝    `q–à‹ò˝ È #òò@d)ò˛
  10821.  @»ò" Ë˚ È !òôê@d*ò˝    àê Δ<˝ È  è‡@d'ò˛
  10822. vê†b ˚ È ¸ˇ@d%ò˛ ˛à꿆z˝ È ¯@dò˙Ä
  10823.  @n˙ È¯Äd%ò˛    1@ Hܸ È˘Äd"ò˝Ä(Ä`ÀÇ˙ È˘ˇ˛dò˛4@`û˚ ÈÛdò˛$ ú˘ ÈÛdò˛dë ò˚ ÈÛdò˛    ‡pAĢ ÈÛdò˛¡Ä "˙ ÈÛdò˛    ∞˛¿˙ ÈÛdò˛0@˛‡¸ ÈÛdò˝ê˛0˙ ÈÛdò¸¿˛¸ ÈÛdò¸    Ä˛ ˙ ÈˇÛdò˚@¡¸ ÈÛdò¸ 0 ˙ È˜U@dò¸ @¸ È|Ûdò¸˛˙ ÈDÛdò¸Ä˝ ÈDÛdò¯AÄ¿˚ ÈDÛdò¸˛
  10824. pÄ@˝ È «êÛdò˚âÄ@˚ È    Ûdò¸˛pÄ@˝ ÈÇÛdò¸Ä`˚ ÈDÛdò˘Ä0˝ È(Ûdò¸pp¿˚ ÈÛdò˙Ä@¿@˚ ÈÛdò¸Ä@˘ ÈÛd ò¸AÄ
  10825. @˚?Áˇ˘ˇ˛dò¸ 
  10826. @€˘Ädò¸,˘‚¯Ädò¸4Ä€ ¯@dò¸√i˙‚ ¯@dò¸x~HB € ¿˛ @d ò¸¿˛–4 ˚‚  ˛ @dò˝Ä† €  «√áå@dò˘ ˚‚  ffLÃ@dòˆP€  Êf Ã@dò˘
  10827. Äê˚‚  ffÃ@dò˘€  ff @dò˘`H ˚‚  &ffLL@dò˘Ä€  √Êcáå@gò˘ĸ‚ ¯@dò˘˛Ä‹ ¯@dò˘¯‚ ¯@gò˘ı Ä˝˚f1ÄÙ¯Äg"ò˘¯0Ä˝ ˚`0Û˘Äd%ò˘ı8è√Δf√Êyèı˘ˇ˛d"ò˘¯
  10828. <ëôôòå˛fff1ôôÄÍdò˘ı.èôôòå˛fff1ôôÄÍdòÔ'˛ô
  10829. ¯ågÊfÊf1ôôÄÍdòÏ#˛ô
  10830. Äåfff1ôôÄÍdòÔ!˛ô
  10831. àåf&d&f1ôôÄÍdòÏ èôò c«¯√ÊèÄÍd
  10832. òÔ÷d òœ¯ˇÄdòÔ‚¯ˇ‡d
  10833. òœ˜ˇdòÔ„¯¯dò–«˘ˇ˛8dòÔ„ÿ˘ºf
  10834. ò–ê¯úfòÔ„†¯\g
  10835. ò–†¯\fòÔ?Áˇ¯†¿` \fòÌ Á†` \fòÔ Á†fgΔcèÄ\fòÌ Á†˝fL¿\fòÔ Á†Δffg ¿\g$òÌ ``˝ÅÄÛ†ffcå¿\d%òÔ 2˛`˝ÄÚ†ffaÿ\d%òÌ 0g¸|c¿>l˛ÒéÛ†ffdÿ\d%òÔ 8˝f`fq˛ôÛ†ÁΔcå¿\dòÌ ˝f`f`˘ôôòÛ†¯\d!òÔ ˛fg‡fa˛ôòÛ†¯\dòÌ ˝ffa˛ôòÛ†¯\dòÔ &˝f fa˝ôÛê¯úd òÌ  ff|c¿>`˘ÒôéÛÿ˘ºd òÔ ˛`ÄÒ«˘ˇ˛8dòÌ ˛`FÄÒ¯¯dòÔ ˚<Ó˜ˇdòÌ Á¯ˇ‡gòÔ Á¯ˇÄdòÌ?Áˇ¯Ûd
  10836. òÔ÷dò√d
  10837. òÔ÷dò√d
  10838. òÔ÷dò√dò√dò√dò√dò√dò√dò√dò√dò√dò√dü√ˇ‰ü√ˇÁÄ√Ä√¬ˇ¸¡¡¡¡¡¡¡¬¡¡¡¡¡¡¬¬¬¬¬¬¬¡¡¡¡¡¬¡¡¡¡¡¡¡¡¬¡¡¡¡¡¬¡¡¡¡¡¡¡¡¬¡¡¡¬¡¡¡¡¡¡¡¡¡¡¡¬¡¡¡¡¡¡¡¡¡¡¡¡¬#˚à˝@@@˝˛ @¬@@ Á"˚¸¿¿@˝˛ @@@Á'˚!yÁ(@@†Yèp"xFXqp<√Ñ8xDÈ&˚âÄH@@†"fHàà"DB"dâÄ˝Dà"DÈ'˚!âÄâ@@DHàà"DB DâDCƒDà"(È&˚âÅ@@"DHà¯"DBD˘˝Dà"È&˚â¸@@¯"DHàÄ"DBDÅ˝Dà"(È&˚â2Ä@@"DHàà&DB"Dâ˝Dà"DÈ'˚!x“@@DOpxBDq<Cƒ8xDÈ˘ıˆÊ˘àıˆàÊ
  10839. ˘pÊpÊˇH@ˇ ˇˇˇˇ@
  10840. ˇ·ˇ‚7^
  10841. 4*\˜, Palatino
  10842. .+l"CHAPTER €`)\1,     Helvetica
  10843.     (@lThe Edition Manager4⁄*˙¯
  10844. (‡*1 )-c)29
  10845.     )9Using ◊P)The Edition Manager
  10846. (ÔlDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯,
  10847. Courier
  10848. .°dONLNd\lh(elTYPE NewPublisherReply = °dONLNdj~v¢+RECORD°dONLNd$xêÑΔ+    canceled:°dONLNd2xÍÑ)ZBoolean;°dONLNd?xDч)Z{user canceled dialog box}°dONLNd\ÜêíÃ(èê
  10849. replacing:°dONLNdkÜÍí)ZBoolean;°dONLNdxÜDí»)Z{user chose existing }°dONLNdõîD†‡*{ filename for an edition}°dONLNd∏¢êÆ¿(´êusePart:°dONLNd≈¢ÍÆ)ZBoolean;°dONLNd“¢DÆÚ)Z{always FALSE in version 7.0}°dONLNdÚ∞꺿(πêpreview:°dONLNdˇ∞ͺ)ZHandle;°dONLNd ∞DºÏ)Z{handle to 'prvw', 'PICT', }°dONLNd4æD ‘*{ 'TEXT', or 'snd' data}°dONLNdOÃêÿ‰(’êpreviewFormat:°dONLNdbÃÍÿ,)Z FormatType;°dONLNdrÃDÿ™)Z{type of preview}°dONLNdÜ⁄êÊÃ(„ê
  10850. container:°dONLNdï⁄ÍÊh)ZEditionContainerSpec;°dONLNdπËDÙ§+Z{edition chosen}°dONLNdÀˆ~ñ(ˇ~END;°dONLNd–ls(lYï°dONLNd—rÖ)ou fiï°dONLNd÷Ö¨)
  10851. ll in the ï°dONLNd‡¨÷)'usePartï°dONLNdÁ÷€)*, ï°dONLNdÈ€)preview™°dONLNd    )), ™°dONLNdÚ    W)
  10852. previewFormat™°dONLNdˇWo)N, and ™°dONLNdo•)    container™°dONLNd•Æ)6 fi™°dONLNdÆÙ)    elds of the new .°dONLNd!l&ú(#l publisher rÒ@°dONLNd,ú&µ)0eply ryİdONLNd2∂&»)ecoṙ°dONLNd6»&–)d..°dONLNd9,l8≥(5lAlways set the °dONLNdH,≥8›)GusePart°dONLNdO,›8Ê)* fi°dONLNdR,Ê8)    eld to F¬†°dONLNdZ,8:)!
  10853. ALSE. The ¬†°dONLNdd,:8d)3preview¬†°dONLNdk,d8m)* fi¬†°dONLNdn,m8◊)    eld contains either NILd@°dONLNdÖ,◊8ˆ)j or the ˇˇ<¯°dONLNdç8lDÿ(Aldata to display in the prÉ8°dONLNd¶8ÿDÙ)leviewò8°dONLNd´8ÛD
  10854. ). The ˇ˝∂Ë(°dONLNd±8 DY)
  10855. previewFormatˇˇ<¯(°dONLNdæ8YDa)N fiO °dONLNd¡8aD¯)#eld should contain 'PICT', 'TEXT', .°dONLNd‰DlPô(Ml or 'prvw'. .°dONLNdVlbè*Set the °dONLNd¯Vèb≈)#    container°dONLNdV≈bŒ)6 fi°dONLNdVŒbˆ)    Celd to be the default name and folder for the edition. The default .°dONLNdGbln´(kl
  10856. name should rC °dONLNdTb¨n∂)@eflİdONLNdWb∑n`) 'ect the data contained in the publishero‡°dONLNd~b_nÚ)®#. For example, if a user publishes °dONLNd°nlzŸ(wlVa bar chart of sales information entitled “sales data,” then the default name for the °dONLNd˜zlÜ◊* Pedition could also be “sales data.” Otherwise, you should use the document name °dONLNdGÜlí€* Qfollowed by a hyphen (-) and a number to establish uniqueness. For example, your °dONLNdòílû*  default name could be “January T@°dONLNd∏íû*)ï otals - 3.”°dONLNdƒ§l∞€(≠lRIf the document has not been saved, the default name should be “untitled edition <ê °dONLNd§€∞‡(≠€n@°dONLNd§·∞Ó)>” °dONLNd∞lºÇ(πlwher7°dONLNd∞ɺä)e ưdONLNd ∞äºè)n¿°dONLNd!∞êºÍ)O is a number to establish uniqueness. The default folder should be the same as °dONLNdpºl»(≈l%the edition for the last publisher crˇ`°dONLNdﺻ¡)ò,eated in the same document. If this is the fiİdONLNd¬º¬»œ)ærst °dONLNdΔ»l‘Œ(—lQpublisher in the document, the default folder should be the same folder that the °dONLNd‘l‡≤* document is in. .°dONLNd(ÊlÚÄ*The °dONLNd,ÊÄÚ∞)canceled°dONLNd4Ê∞Úπ)0 fi°dONLNd7ÊπÚ-)    eld of the new publisher rR`°dONLNdQÊ-ÚH)teply r$¿°dONLNdWÊHÚZ)ecor˜ °dONLNd[ÊYÚ›)d indicates whether the user °dONLNdxÚl˛ù(˚l canceled frR`°dONLNdÉÚù˛)1om the dialog box. The R`°dONLNdöÚ˛<)i    replacingR`°dONLNd£Ú<˛E)6 fiR`°dONLNd¶ÚE˛Â)    %eld indicates that the user chose to °dONLNdÀ˛l
  10857. p(lrR`°dONLNdÃ˛p
  10858. Ì)eplace an existing edition fiR`°dONLNdÈ˛Ì
  10859. )}le. If R`°dONLNd˛
  10860. ;)    replacingR`°dONLNd˘˛;
  10861. A)6 r$¿°dONLNd˚˛A
  10862. d)eturns Fg`°dONLNd˛c
  10863. ®)"ALSE, call the °dONLNd
  10864. l(lCreateEditionContainerFile°dONLNd,
  10865. C)ú function to crR`°dONLNd;
  10866. Cç);eate an edition f"‡°dONLNdL
  10867. çü)Jile. °dONLNdRl(Ä(%lThe °dONLNdVÄ(∂)    container°dONLNd_∂(ø)6 fi°dONLNdbø()    eld is of data type °dONLNdv(å)UEditionContainerSpec°dONLNdäå(è)x.°dONLNdå4l@(=lTYPE EditionContainerSpec = °dONLNd™B~N¢+RECORD°dONLNd≥Pê\¿+theFile:°dONLNd¿PÍ\)ZFSSpec;°dONLNdÃPD\‡)Z{file containing edition }°dONLNdÛ^Djn*{ data}°dONLNd˝lêx‰(uêtheFileScript:°dONLNdlÍx,)Z ScriptCode;°dONLNd lDx⁄)Z{script code of filename}°dONLNd<zêÜ¿(ÉêthePart:°dONLNdIzÍÜ)ZLongInt;°dONLNdVzDÜ»)Z{which part of file, }°dONLNdyàDîŒ*{ always kPartsNotUsed}°dONLNdìñê¢ÿ(üê thePartName:°dONLNd§ñÍ¢)ZStr31;°dONLNdØñD¢⁄)Z{not used in version 7.0}°dONLNdÀ§ê∞‰(≠êthePartScript:°dONLNdfi§Í∞,)Z ScriptCode;°dONLNdÓ§D∞⁄)Z{not used in version 7.0}°dONLNd        ≤~æñ(ª~END;ˇÊ@ˇ ˇˇˇˇ@
  10868. ˇ·ˇ‚7^
  10869. 4H\, Palatino
  10870. .+ä"CHAPTER €`)\1,     Helvetica
  10871.     (@äThe Edition Manager4⁄ä˙(‡äUsing ◊P)The Edition Manager
  10872. ~¿(‡1
  10873. ‡)-a¿)30
  10874. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿
  10875. .°dONLNd\äh•(eäThe fi°dONLNd\•h∂)eld ,
  10876. Courier°dONLNd
  10877. \∂h‡)theFile°dONLNd\‡h)*  is of type °dONLNd\h2).FSSpec°dONLNd#\2h)$2. See the File Manager chapter in this volume for .°dONLNdUhätˆ(qäfurther information on fi,†°dONLNdnh˜t?)mle system specifi5‡°dONLNdh?t`)Hcation r\¿°dONLNdáh`tr)!ecor— °dONLNdãhrt~)ds.°dONLNdèzäÜê(ÉäY@İdONLNdêzêÜ?)(ou identify the edition using a volume r†°dONLNd∏z@ÜP)∞efer≠¿°dONLNdºzPÜâ) ence number5†°dONLNd«zâÜö)9, dir˛¿°dONLNdÃzöÜ·)ectory ID, and fiᇰdONLNd›z‚Ü)Hlename. °dONLNdÂÜäíY(èä.When specifying an edition, follow the standar‡°dONLNdÜYíı)œ$d conventions described in the File °dONLNd7íäû(õäManager chapter of this volume.°dONLNdW§ä∞©*After fi&İdONLNd_§™∞‚) lling in the fid°dONLNdn§‚∞X)8elds of the new publisher rx¿°dONLNdâ§X∞q)veply r°dONLNdè§r∞Ñ)ecoru`°dONLNdì§Ñ∞ )!d, pass it as a parameter to the .°dONLNd¥∞予(πäNewPublisherDialog°dONLNdΔ∞ˆºfl)l4 function, which displays the publisher dialog box. °dONLNd˚»ä‘V(—ä"err := NewPublisherDialog (reply);°dONLNd‡äÏo*3After displaying the publisher dialog box, use the °dONLNdQ‡oÏ )ÂCreateEditionContainerFile°dONLNdk‡ Ï
  10878. )ú °dONLNdlÏä¯√(ıäfunction to crR`°dONLNdzÏ√¯8)9eate the edition containerï°dONLNdîÏ7¯v)t, and then use ï°dONLNd£Ïv¯≤)?
  10879. NewSectionï°dONLNd≠Ï≤¯Ì)< function to crg`°dONLNdºÏ̯);    eate the .°dONLNd≈¯äØ(ä    section r≠İdONLNdŒ¯Ø¡)%ecor!‡°dONLNd“¯¬)d and the alias r⁄‡°dONLNd„¯)FecorO@°dONLNdÁ¯7)d. See æ°dONLNdÓ¯7G)“Crö°dONLNdÒ¯G∞)eating the Section RecorY‡°dONLNd    ¯±Õ)jd and `°dONLNd¯Õˇ) Alias Recor{¿°dONLNd¯ˇ
  10880. )2d”óİdONLNd¯
  10881.  )  °dONLNdäW(
  10882. ä1earlier in this chapter for detailed information.°dONLNdOä"ô*In rÙ‡°dONLNdSô"4)$esponse to the user selecting the CrN@°dONLNdw5")ú0eate Publisher menu item, this code illustrates °dONLNdß"ä.@(+ä(how your application might set up the pr© °dONLNdœ"@. )∂0eview for the edition, set the default name for .°dONLNdˇ.ä:È(7äthe edition container¬†°dONLNd.Ë:m)^, and call an application-defi¬†°dONLNd2.m:©)Öned function (¬†°dONLNd@.©:˝)<DoNewPublisher¬†°dONLNdN.˝:ˇ)T .°dONLNdO:äFÇ(Cä9function) to display the publisher dialog box on the user◊@°dONLNdà:ÉFô)˘’s scrÕ¿°dONLNdé:ôF≠)een. ‘°dONLNdì:≠F)An application might .°dONLNd®FäR∞(Oä    call the °dONLNd±F∞R)&DoNewPublisher°dONLNdøFRD)T function as a rR`°dONLNdœFDR)@-esult of the user making a menu selection to .°dONLNd¸Rä^í([äcrµ@°dONLNd˛Rí^ı)eate a publisher or in r°dONLNdRˆ^l)desponse to handling the Cr’@°dONLNd0Rl^Ï)veate Publisher event. See the }‡°dONLNdNRÏ^    )ÄApple °dONLNdT^äjÛ(gäOEvent Manager chapter in this volume for an example handler that handles the Cr7`°dONLNd£^Ùj(gÙeate °dONLNd®jäv‘(säPublisher event. .°dONLNd∫Çäéú*VAR°dONLNdøêúú+thisDocument: °dONLNd‘êúå)~MyDocumentInfoPtr; °dONLNdÈûú™(ßúpromptForDialog: °dONLNdû™J)~Boolean;°dONLNd ¨ú∏“(µú    preview: °dONLNd¨∏J)~Handle; °dONLNd%∫úΔˆ(√úpreviewFormat: °dONLNd;∫Δb)~ FormatType; °dONLNdI»ú‘(—údefaultLocation: °dONLNda»‘ò)~EditionContainerSpec;°dONLNdx‰ä®(ÌäBEGIN°dONLNdÚú˛+?{Get a preview to show the user. The MyGetPreviewForSelection }°dONLNd¿ú §*,{ function returns a handle to the preview.}°dONLNdÓú»*2preview := MyGetPreviewForSelection(thisDocument);°dONLNd"ú(,*previewFormat := 'TEXT';°dONLNd<*ú6Ú*9defaultLocation := MyGetDefaultEditionSpec(thisDocument);°dONLNdw8úD,*promptForDialog := TRUE;ˇ˛Ã»°dONLNdëFúR*@myErr := DoNewPublisher(thisDocument, promptForDialog, preview, °dONLNd€T,`Ï+ê previewFormat, defaultLocation);°dONLNd¸bän¢(käEND;
  10883. éHï4èHï êäê
  10884. ˇ·ˇ‚7^
  10885. .°dONLNdÅäèó* Crà°dONLNdÅóè-)
  10886. eating the Edition Containerˇˇˇˇˇˇ(ã1
  10887. .°dONLNd ïä°Ø(ûäUse the °dONLNd(ïØ°K)%CreateEditionContainerFile°dONLNdBïK°Ü)ú function to crR`°dONLNdQïܰ);eate an edition container to .°dONLNdn°ä≠Û(™ähold the publisher data.ˇé@ˇ ˇˇˇˇ@
  10888. ˇ·ˇ‚7^
  10889. 4*\˜, Palatino
  10890. .+l"CHAPTER €`)\1,     Helvetica
  10891.     (@lThe Edition Manager4⁄*˙¯
  10892. (‡*1 )-c)31
  10893.     )9Using ◊P)The Edition Manager
  10894. (ÔlDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯,
  10895. Courier
  10896. .°dONLNd\lh»(el:err := CreateEditionContainerFile (editionFile, fdCreator,°dONLNdFj2v8+Δ °dONLNdGj8v») editionFileNameScript);.°dONLNd`Çlé±(ãlThis function cr€°dONLNdpDZé")Eeates an edition container0İdONLNdäÇ"éÛ)q3. The edition container is empty (that is, it does °dONLNdΩélö(ól¬ contain any formats) at this time.°dONLNd‰†l¨r*Tµ¿°dONLNd†q¨Å)o cr‡Ä°dONLNdȆŨR)0eate a customized icon for the edition containernİdONLNd†R¨Å)— , put the crÿ°dONLNd%†Ũæ)/eator signaturU@°dONLNd3†ø¨È)>
  10897. e of your °dONLNd=¨l∏Ï(µlYapplication with the icon in your application’s bundle. See the Finder Interface chapter °dONLNdñ∏lƒÒ* Yin this volume for additional information. Depending on the contents of the edition, the °dONLNdÔƒl–r* fiå¿°dONLNdÒƒr–™)Ple type will be 'edtp' (for graphics), 'edtt' (for text), or 'edts' (for sound)..°dONLNdB÷l‚è(fllAfter crR`°dONLNdJ÷è‚
  10898. )#eating the edition containerï°dONLNdf÷ ‚3)}
  10899. , use the ï°dONLNdp÷3‚o)'
  10900. NewSectionï°dONLNdz÷o‚™)< function to crg`°dONLNdâ÷™‚Û);eate the section .°dONLNdö‚lÓo(ÎlrE°dONLNdõ‚pÓÇ)ecorπ`°dONLNdü‚ÇÓ∏)
  10901. d and alias r°dONLNd¨‚πÓÀ)7ecorâ`°dONLNd∞‚ÀÓ)d for the section..°dONLNd√Ùlú(˝l Listing 1-4°dONLNdŒÙú˘)0 illustrates how to crR`°dONLNd‰Ù˘C)]eate a publisherï°dONLNdÙÙB[)I. The ï°dONLNd˙Ù[Ø)DoNewPublisherï°dONLNdÙØˆ)T function shown .°dONLNdl Ë(    lin the listing is a function pr™‡°dONLNd7Ë ˜)|>ovided by an application. Note that an application might call .°dONLNdu l~(lthe °dONLNdy ~“)DoNewPublisher°dONLNdá “)T function as a rR`°dONLNdó ›)@/esult of the user making a menu selection to cr$¿°dONLNdΔ ›Û)Àeate .°dONLNdÀl$ª(!la publisher or in rì °dONLNdfiª$1)Oesponse to handling the CrJ`°dONLNd¯2$≤)weate Publisher event. See the Û°dONLNd±$Î) Apple Event °dONLNd"$l0π(-lIManager chapter in this volume for an example handler that handles the Cr°dONLNdk$∫0Œ(-∫eate °dONLNdp0l<≥(9lPublisher event..°dONLNdÅBlN”*The parameters to the °dONLNdóB”N')gDoNewPublisher°dONLNd•B'N‡)T+ function include a pointer to information .°dONLNd–NlZÂ(WlVabout the document, a Boolean value that indicates if the function should display the °dONLNd&Zlf¸*  new publisher dialog box, the prY†°dONLNdFZ¸fw)êeview for the edition, the prO¿°dONLNdcZwf◊){eview format, and an °dONLNdxflr∑(oledition containerÒİdONLNdâf∂r∏)J.°dONLNdãxlÑI(Ål3The function displays the publisher dialog box if rcİdONLNdæxIщ)›%equested, letting the user accept or °dONLNd„ÑlêW(çl4change the name of the edition and the location wher_İdONLNdÑWêµ)Îe the edition should rö°dONLNd-ѵêÙ)^eside. Use the .°dONLNd<êlú(ôlCreateEditionContainerFile°dONLNdVêúC)ú function to crR`°dONLNdeêCúÓ);%eate the edition with the given name °dONLNdäúl®Œ(•land location. Use the °dONLNd†úŒ®
  10902. )b
  10903. NewSection°dONLNd™ú
  10904. ®E)< function to crR`°dONLNdπúE®Â);$eate a new section for the publisherï°dONLNd›ú‰®Á)ü..°dONLNdflÆl∫…(∑lAfter the section is cr∫@°dONLNdˆÆ…∫£)]2eated, you must write out the edition data. Be sur¯@°dONLNd(Æ£∫˜)⁄e to add the newly °dONLNd;∫lΔt(√lcrµ@°dONLNd=∫tΔ{)>eated section to your list of sections for this document. Ther4@°dONLNd{∫|Δå(√|e arB‡°dONLNd∫åΔ¡)
  10905. e several difà`°dONLNdå∫¡ΔÕ)5ferj‡°dONLNdè∫ÕΔ›) ent °dONLNdìΔl“µ(œltechniques for crİdONLNd§Δ∂“È)JGeating publishers and unique IDs; this listing displays one technique. ˇ 0@ˇ ˇˇˇˇ@
  10906. ˇ·ˇ‚7^
  10907. 4H\, Palatino
  10908. .+ä"CHAPTER €`)\1,     Helvetica
  10909.     (@äThe Edition Manager4⁄ä˙(‡äUsing ◊P)The Edition Manager
  10910. ~¿(‡1
  10911. ‡)-a¿)32
  10912. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿
  10913. gHj4gHj"gHa
  10914. ˇ·ˇ‚7^
  10915.     °dONLNdˇˇ(dä Listing 1-4°dONLNd\Œg)DCreating a publisher,
  10916. Courier
  10917. .°dONLNdsH,(|H&FUNCTION DoNewPublisher(thisDocument: °dONLNdIsDº)¸MyDocumentInfoPtr;  °dONLNdfÅÿç⁄(äÿ+promptForDialog: Boolean; preview: Handle; °dONLNdöèÿõ2*previewFormat: °dONLNdØèDõå)l FormatType; °dONLNdƒùÿ©&(¶ÿ
  10918. editionSpec: °dONLNd◊ùD©¯)lEditionContainerSpec) : OSErr;°dONLNdˆ´H∑Z(¥HVAR°dONLNd¸πl≈+$getLastErr, dialogErr:°dONLNdπ¸≈ )êOSErr;°dONLNd#«l”(–lcreateErr, sectionErr:°dONLNdA«¸” )êOSErr;°dONLNdJ’l·ê(filresID:°dONLNdX’¸·,)êInteger;°dONLNdc„lÔ∫(Ïl
  10919. thisSectionH:°dONLNdx„¸ÔP)êSectionHandle;°dONLNdâÒl˝ê(˙lreply:°dONLNdóÒ¸˝h)êNewPublisherReply;°dONLNd™ˇH f(HBEGIN°dONLNd≤
  10920. lt+$,{Set up info for new publisher reply record}°dONLNd·l'*reply.replacing := FALSE;°dONLNd˝)l5ˆ*reply.usePart := FALSE;°dONLNd7lC*reply.preview := preview;°dONLNd3ElQJ*%reply.previewFormat := previewFormat;°dONLNd[Sl_&*reply.container := editionSpec;°dONLNd}mly¸*IF promptForDialog THEN °dONLNdò{láä*BEGIN°dONLNd¶{áº)¢{user interaction is allowed}°dONLNdœâï*){Display dialog box and let user select.}°dONLNd¸ó~£h(†~'dialogErr := NewPublisherDialog(reply);°dONLNd'•~±D*!{Dispose of preview data handle.}°dONLNdL≥~ø&*DisposHandle(reply.preview);°dONLNdl¡~Õ‡*;{There's usually no error returned here, but if there is, }°dONLNd´œ~€⁄*:{ then it makes no sense to continue with this operation.}°dONLNdÈ›~È∞*3IF dialogErr <> noErr THEN MyErrHandler(dialogErr);°dONLNd Î~˜2*{Do nothing if user canceled.}°dONLNdB˘~*IF reply.canceled THEN °dONLNd]~ú*BEGIN°dONLNdgê!b+#DoNewPublisher := userCanceledErr; °dONLNdè#ê/*EXIT(DoNewPublisher);°dONLNd®1~=ñ(:~END;°dONLNdØ?lKÑ(HlEND;°dONLNd∂MlY‡*>{If user wants to replace an existing file, don't create one.}°dONLNd˜[lg*IF NOT reply.replacing THEN°dONLNdiluä*BEGIN°dONLNdw~ÉÃ+
  10921. createErr := °dONLNd0Öêë»+4CreateEditionContainerFile(reply.container.theFile, °dONLNddìHüú(úHkAppSignature,°dONLNdİ2≠Ï+Íreply.container.theFileScript);ˇ ¯@ˇ ˇˇˇˇ@
  10922. ˇ·ˇ‚7^
  10923. 4*\˜, Palatino
  10924. .+l"CHAPTER €`)\1,     Helvetica
  10925.     (@lThe Edition Manager4⁄*˙¯
  10926. (‡*1 )-c)33
  10927.     )9Using ◊P)The Edition Manager
  10928. (ÔlDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯,
  10929. Courier
  10930. .°dONLNd\`h‘(e`>{If the create failed, then this operation can't be completed}°dONLNdBj`v¸*IF createErr <> noErr THEN°dONLNd`x`Ñ~*BEGIN°dONLNdjÜríb+(DoNewPublisher := errAEPermissionDenied;°dONLNdóîr†*EXIT(DoNewPublisher);°dONLNd∞¢`Æx(´`END;°dONLNd∑∞Nºf(πNEND;°dONLNdææN ™*:{Advance counter to make a new unique sectionID for this }°dONLNd˚ÃNÿ‘*A{ document. It is not required that you equate section IDs with }°dONLNd?⁄NÊú*
  10931. { resources.}°dONLNdOËNÙ»*?thisDocument^.nextSectionID := thisDocument^.nextSectionID + 1;°dONLNdëN¸*{Create a publisher section.}°dONLNd±NJ**sectionErr := NewSection(reply.container, °dONLNdÈfi*Ä+ê thisDocument^.fileSpecPtr,°dONLNd
  10932. ,∫8¿(5∫ °dONLNd,fi8⁄)$* stPublisher, thisDocument^.nextSectionID,°dONLNdC:∫F¿(C∫ °dONLNdF:fiFz)$ pumOnSave, thisSectionH);°dONLNdcHNT⁄(QNBIF (sectionErr <> noErr) & (sectionErr <> multiplePublisherWrn) & °dONLNd©V`bJ+'(sectionErr <> notThePublisherWrn) THEN°dONLNd‘d`p∞*8{If a new section could not be created, don't continue }°dONLNdr`~*{ with this operation. }°dONLNd,Ä`åˆ*MyErrHandler(sectionErr);°dONLNdHöN¶,(£N%resID := thisDocument^.nextSectionID;°dONLNdp¥N¿™*:{Add this section/alias pair to my internal bookkeeping. }°dONLNd≠¬NŒ∞*;{ The AddSectionAliasPair is a routine to accomplish this.}°dONLNdΖN‹ò*7AddSectionAliasPair(thisDocument, thisSectionH, resID);°dONLNd%ÍNˆÍ*{Write out first edition.}°dONLNdB¯NP*+DoWriteEdition(thisSectionH, thisDocument);°dONLNdpN§*9{Remember that the section and alias records need to be }°dONLNd¨ N,ò*7{ saved as resources when the user saves the document.}°dONLNdÊ:NF8*'{Set the function result appropriately}°dONLNdHNT*!DoNewPublisher := MyGetLastError;°dONLNd2b*n®(k*END; {DoNewPublisher}
  10933. é*ï¯4è*ﯠêlê¯
  10934. ˇ·ˇ‚7^
  10935. .°dONLNdHÅlè(+B !Opening an Edition Container to Wç°dONLNdiÅ(èV)º    rite Dataˇˇˇˇˇˇ) 1
  10936. °dONLNdsïl°í(ûl    Several r@°dONLNd|ïì°æ)'
  10937. outines ar›†°dONLNdÜïæ°…)+e rÏ@°dONLNdâï…°‡) equirİdONLNdéï·°[)ed to write (publish) data frÌİdONLNd´ïZ°Ÿ)yom a publisher to an edition .°dONLNd»°l≠ñ(™l    container¬†°dONLNd—°ï≠≥)). Beforï°dONLNdÿ°≥≠)/e writing data to an edition, you must use the ï°dONLNd°≠”)ÃOpenNewEditionï°dONLNd°”≠’)T ˇ‘@ˇ ˇˇˇˇ@
  10938. ˇ·ˇ‚7^
  10939. 4H\, Palatino
  10940. .+ä"CHAPTER €`)\1,     Helvetica
  10941.     (@äThe Edition Manager4⁄ä˙(‡äUsing ◊P)The Edition Manager
  10942. ~¿(‡1
  10943. ‡)-a¿)34
  10944. (ÔäDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^H¿
  10945. °dONLNd\äh(eäXfunction. This function should be used only for a publisher within a document. Use this °dONLNdXhäto* 8function to initiate the writing of data to an edition. ,
  10946. Courier.°dONLNdëÄäå¬*4err := OpenNewEdition (publisherSectionH, fdCreator,°dONLNdÕéö+~ °dONLNdŒéö‡)# publisherSectionDocument, refNum);.°dONLNdÚ¶ä≤ë(ØäA∫†°dONLNdÛ¶ë≤)Y user may try to save a document containing a publisher that is unable to write its data °dONLNdL≤äæl(ªä2to an edition—because another publisher (that sharÿ`°dONLNd~≤læı)‚!es the same edition) is writing, °dONLNdüæä («äanother subscriber (that shar, °dONLNdºæ     p)es the same edition) is rË`°dONLNd’æp )g"eading, or a publisher located on °dONLNd˜ ä÷È(”äanother computer is r¬‡°dONLNd  È÷)_egister°dONLNd ÷Ì)6ed to the section. In such a case, you may decide to r∞¿°dONLNdI Ì÷    )Êefrain °dONLNdP÷ä‚ë(fläfrò‡°dONLNdR÷ë‚´)Bom writing to the edition so that the user does not have to wait. I°dONLNdî÷¨‚≤(fl¨Y    Ä°dONLNdï÷≤‚˘)ou should also rı °dONLNd•÷¯‚)Fefrain °dONLNd¨‚äÓë(Îäfrò‡°dONLNdÆ‚ëÓÌ)om displaying an err∏†°dONLNd¬‚ÌÓ')\or to the usery°dONLNd–‚'Ó∏):". The contents of the publisher ar`†°dONLNdÚ‚∏Ó)ëe saved to disk with °dONLNdÓä˙(˜äYthe document. The next time that the user saves, you can write the publisher data to the °dONLNd`˙äÆ*     edition. ë¿°dONLNdi˙Æ¥)$YR@°dONLNdj˙¥7)ou should discourage users fr-†°dONLNdá˙7)É0om making multiple copies of the same publisher °dONLNd∑äÒ(äPand pasting them in the same or other documents by displaying an alert box (see °dONLNdäB* (“Duplicating Publishers and Subscribers”»@°dONLNd/B¢)∏ later in this chapter). °dONLNdI$ä0¯(-äTIf a user clicks Send Edition Now within the publisher options dialog box (to write °dONLNdù0ä<* ]publisher data to an edition manually), and the publisher is unable to write its data to its °dONLNd˙<äH* edition (for any of the rİdONLNd<ÒHÕ)g1easons outlined above), you should display an errU†°dONLNdD<ÕH)‹ or message. .°dONLNdQNäZ¡(Wä After you arR`°dONLNd]N¡Zœ)7e fiR`°dONLNdaNœZå)+nished writing data to an edition, use the R`°dONLNdåNåZ‘)Ω CloseEditionR`°dONLNdòN‘Z)H
  10947.  function to .°dONLNd•Zäf‘(cäclose the edition.°dONLNd∏läx∏* Listing 1-5 @°dONLNd√lπxw)/. illustrates how to write data to an edition. ˜†°dONLNdÒlvxŒ)ΩAs described earlierb`°dONLNdlŒxˇ)X , you must .°dONLNdxäÑX(Åä.open the edition, write each format using the °dONLNd>xXц)Œ WriteEdition°dONLNdJx†Ñ)H function, and close the °dONLNdcÑäêÿ(çäedition using the °dONLNduÑÿê )N CloseEdition°dONLNdÅÑ ê)H4 function. This listing shows how to write text onlyd@°dONLNdµÑê)„. If .°dONLNd∫êäú(ôä#the edition is written successfully@°dONLNd›êúZ)ì, subscribers r5 °dONLNdÏêZú‘)=eceive Section Read events. 
  10948. æH¬4øH¡"øHa
  10949. ˇ·ˇ‚7^
  10950.     °dONLNdˇˇ(ºä Listing 1-5°dONLNd    ¥Œø÷)DW’ê°dONLNd
  10951. ¥÷ø1)riting data to an edition
  10952. .°dONLNd$Àä◊Œ(‘ä6PROCEDURE DoWriteEdition(thePublisher: SectionHandle);°dONLNd[ÂäÒú*VAR°dONLNd`ÛúˇÃ+eRefNum:°dONLNdmÛˆˇJ)ZEditionRefNum;°dONLNd}ú
  10953. Ã(
  10954. úopenErr:°dONLNdäˆ
  10955. )ZOSErr;°dONLNdíú“(ú    writeErr:°dONLNd†ˆ)ZOSErr;°dONLNd®ú)“(&ú    closeErr:°dONLNd∂ˆ))ZOSErr;°dONLNdæ+ú7Í(4ú
  10956. thisDocument:°dONLNd–+ˆ7b)ZMyDocumentInfoPtr;°dONLNd‰9úEfi(Bú textHandle:°dONLNdÙ9ˆE )ZHandle;°dONLNd¸Sä_®(\äBEGIN°dONLNdaúmŒ+3{Find out which document this section belongs to. }°dONLNd8oú{∂*/{ The FindDocument function accomplishes this.}°dONLNdi}úâû*+thisDocument := FindDocument(thePublisher);ˇ.@ˇ ˇˇˇˇ@
  10957. ˇ·ˇ‚7^
  10958. 4*\˜, Palatino
  10959. .+l"CHAPTER €`)\1,     Helvetica
  10960.     (@lThe Edition Manager4⁄*˙¯
  10961. (‡*1 )-c)35
  10962.     )9Using ◊P)The Edition Manager
  10963. (ÔlDraft. PreliminaryVP):, Confi)dential. ©1991 ˘Å)0Apple ComputerÒ)7, Inc. Ìë)1/7/924^*¿¯,
  10964. Courier
  10965. .°dONLNd\~h (e~{Open edition for writing.}°dONLNdj~v¬*6openErr := OpenNewEdition(thePublisher, kAppSignature,°dONLNdXx¥Ñ¿+6  °dONLNd\xÿщ)$  °dONLNdaxÑÚ)6&  thisDocument^.fileSpecPtr, eRefNum);°dONLNdâÜ~í(è~IF openErr <> noErr THEN°dONLNd£î~†Ü*,{If the open failed, then you can't write, }°dONLNd‘¢~Æt*){ so don't continue with this operation.}°dONLNd∞~º*MyErrHandler(openErr);°dONLNd ~÷∞*3{Get the text data to write. The GetTextInSection }°dONLNdNÿ~‰2*{ function accomplishes this.}°dONLNdnÊ~Ú‡*;textHandle := GetTextInSection(thePublisher, thisDocument);°dONLNd´~ *{Write out text data.}°dONLNd√~Í*HLock(textHandle);°dONLNd◊~(¬*6writeErr := WriteEdition(eRefNum, 'TEXT', textHandle^,°dONLNd*¥6∫+6 °dONLNd*ÿ6fi)$ °dONLNd*6∂)6 GetHandleSize(textHandle));°dONLNd78~Dˆ(A~HUnLock(textHandle);°dONLNdMF~R*IF writeErr <> noErr THEN°dONLNdhT~`ú*BEGIN°dONLNdpbênÊ+9{There were problems writing; simply close the edition. }°dONLNd¨pê|‡*8{ When successful = FALSE, the edition data <> section }°dONLNdÁ~êä‘*6{ data. Note: this isn't fatal or bad; it just means }°dONLNd åêòÚ*;{ that the data wasn't written and no Section Read events }°dONLNd^öê¶*{ will be generated.}°dONLNdv®ê¥Ü*)closeErr := CloseEdition(eRefNum, FALSE);°dONLNd°∂~¬Æ(ø~END ELSE°dONLNd´ƒ~–ú*BEGIN°dONLNd≥“êfi¬+3{The write was successful; now close the